123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370 |
- //*@@@+++@@@@******************************************************************
- //
- // 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"
- #include "strTransform.h"
- #include <math.h>
- #include "perfTimer.h"
- #ifdef MEM_TRACE
- #define TRACE_MALLOC 1
- #define TRACE_NEW 0
- #define TRACE_HEAP 0
- #include "memtrace.h"
- #endif
- #ifdef ADI_SYS_OPT
- extern char L1WW[];
- #endif
- #ifdef X86OPT_INLINE
- #define _FORCEINLINE __forceinline
- #else // X86OPT_INLINE
- #define _FORCEINLINE
- #endif // X86OPT_INLINE
- Int inputMBRow(CWMImageStrCodec *);
- #if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC)
- void StrEncOpt(CWMImageStrCodec* pSC);
- #endif // OPT defined
- #define MINIMUM_PACKET_LENGTH 4 // as long as packet header - skipped if data is not accessed (happens only for flexbits)
- Void writeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, U8 cChMode, size_t cChannel, size_t iPos)
- {
- if(cChMode > 2)
- cChMode = 2;
- if(cChannel > 1)
- putBit16(pIO, cChMode, 2); // Channel mode
- else
- cChMode = 0;
- putBit16(pIO, pQuantizer[0][iPos].iIndex, 8); // Y
- if(cChMode == 1) // MIXED
- putBit16(pIO, pQuantizer[1][iPos].iIndex, 8); // UV
- else if(cChMode > 0){ // INDEPENDENT
- size_t i;
- for(i = 1; i < cChannel; i ++)
- putBit16(pIO, pQuantizer[i][iPos].iIndex, 8); // UV
- }
- }
- // packet header: 00000000 00000000 00000001 ?????xxx
- // xxx: 000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved)
- // ?????: (iTileY * cNumOfSliceV + iTileX)
- Void writePacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID)
- {
- putBit16(pIO, 0, 8);
- putBit16(pIO, 0, 8);
- putBit16(pIO, 1, 8);
- putBit16(pIO, (pID << 3) + (ptPacketType & 7), 8);
- }
- Int writeTileHeaderDC(CWMImageStrCodec * pSC, BitIOInfo * pIO)
- {
- size_t iTile, j = (pSC->m_pNextSC == NULL ? 1U : 2U);
- for(; j > 0; j --){
- if((pSC->m_param.uQPMode & 1) != 0){ // not DC uniform
- CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
- size_t i;
-
- pTile->cChModeDC = (U8)(rand() & 3); // channel mode, just for concept proofing!
-
- if(pSC->cTileRow + pSC->cTileColumn == 0) // allocate DC QP info
- for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
- if(allocateQuantizer(pSC->pTile[iTile].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
- return ICERR_ERROR;
-
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- pTile->pQuantizerDC[i]->iIndex = (U8)((rand() & 0x2f) + 1); // QP indexes, just for concept proofing!
-
- formatQuantizer(pTile->pQuantizerDC, pTile->cChModeDC, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- pTile->pQuantizerDC[i]->iOffset = (pTile->pQuantizerDC[i]->iQP >> 1);
-
- writeQuantizer(pTile->pQuantizerDC, pIO, pTile->cChModeDC, pSC->m_param.cNumChannels, 0);
- }
- pSC = pSC->m_pNextSC;
- }
- return ICERR_OK;
- }
- Int writeTileHeaderLP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
- {
- size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U);
-
- for(; k > 0; k --){
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY && (pSC->m_param.uQPMode & 2) != 0){ // not LP uniform
- CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
- U8 i, j;
- pTile->bUseDC = ((rand() & 1) == 0 ? TRUE : FALSE); // use DC quantizer?
- putBit16(pIO, pTile->bUseDC == TRUE ? 1 : 0, 1);
- pTile->cBitsLP = 0;
-
- pTile->cNumQPLP = (pTile->bUseDC == TRUE ? 1 : (U8)((rand() & 0xf) + 1)); // # of LP QPs
-
- if(pSC->cTileRow > 0)
- freeQuantizer(pTile->pQuantizerLP);
-
- if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK)
- return ICERR_ERROR;
- if(pTile->bUseDC == TRUE)
- useDCQuantizer(pSC, pSC->cTileColumn);
- else{
- putBit16(pIO, pTile->cNumQPLP - 1, 4);
-
- pTile->cBitsLP = dquantBits(pTile->cNumQPLP);
-
- for(i = 0; i < pTile->cNumQPLP; i ++){
- pTile->cChModeLP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing!
-
- for(j = 0; j < pSC->m_param.cNumChannels; j ++)
- pTile->pQuantizerLP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing!
- formatQuantizer(pTile->pQuantizerLP, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i, TRUE, pSC->m_param.bScaledArith);
- writeQuantizer(pTile->pQuantizerLP, pIO, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i);
- }
- }
- }
- pSC = pSC->m_pNextSC;
- }
- return ICERR_OK;
- }
- Int writeTileHeaderHP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
- {
- size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U);
-
- for(; k > 0; k --){
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && (pSC->m_param.uQPMode & 4) != 0){ // not HP uniform
- CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
- U8 i, j;
- pTile->bUseLP = ((rand() & 1) == 0 ? TRUE : FALSE); // use LP quantizer?
- putBit16(pIO, pTile->bUseLP == TRUE ? 1 : 0, 1);
- pTile->cBitsHP = 0;
-
- pTile->cNumQPHP = (pTile->bUseLP == TRUE ? pTile->cNumQPLP : (U8)((rand() & 0xf) + 1)); // # of LP QPs
-
- if(pSC->cTileRow > 0)
- freeQuantizer(pTile->pQuantizerHP);
-
- if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK)
- return ICERR_ERROR;
-
- if(pTile->bUseLP == TRUE)
- useLPQuantizer(pSC, pTile->cNumQPHP, pSC->cTileColumn);
- else{
- putBit16(pIO, pTile->cNumQPHP - 1, 4);
- pTile->cBitsHP = dquantBits(pTile->cNumQPHP);
-
- for(i = 0; i < pTile->cNumQPHP; i ++){
- pTile->cChModeHP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing!
-
- for(j = 0; j < pSC->m_param.cNumChannels; j ++)
- pTile->pQuantizerHP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing!
- formatQuantizer(pTile->pQuantizerHP, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i, FALSE, pSC->m_param.bScaledArith);
- writeQuantizer(pTile->pQuantizerHP, pIO, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i);
- }
- }
- }
- pSC = pSC->m_pNextSC;
- }
- return ICERR_OK;
- }
- Int encodeMB(CWMImageStrCodec * pSC, Int iMBX, Int iMBY)
- {
- CCodingContext * pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
-
- if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE && pSC->m_param.bTranscode == FALSE){ // write packet headers
- U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + pSC->cTileColumn) & 0x1F);
-
- if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) {
- writePacketHeader(pContext->m_pIODC, 0, pID);
- if (pSC->m_param.bTrimFlexbitsFlag)
- putBit16(pContext->m_pIODC, pContext->m_iTrimFlexBits, 4);
- writeTileHeaderDC(pSC, pContext->m_pIODC);
- writeTileHeaderLP(pSC, pContext->m_pIODC);
- writeTileHeaderHP(pSC, pContext->m_pIODC);
- }
- else{
- writePacketHeader(pContext->m_pIODC, 1, pID);
- writeTileHeaderDC(pSC, pContext->m_pIODC);
- if(pSC->cSB > 1){
- writePacketHeader(pContext->m_pIOLP, 2, pID);
- writeTileHeaderLP(pSC, pContext->m_pIOLP);
- }
- if(pSC->cSB > 2){
- writePacketHeader(pContext->m_pIOAC, 3, pID);
- writeTileHeaderHP(pSC, pContext->m_pIOAC);
- }
- if(pSC->cSB > 3) {
- writePacketHeader(pContext->m_pIOFL, 4, pID);
- if (pSC->m_param.bTrimFlexbitsFlag)
- putBit16(pContext->m_pIOFL, pContext->m_iTrimFlexBits, 4);
- }
- }
- }
-
- if(EncodeMacroblockDC(pSC, pContext, iMBX, iMBY) != ICERR_OK)
- return ICERR_ERROR;
-
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY)
- if(EncodeMacroblockLowpass(pSC, pContext, iMBX, iMBY) != ICERR_OK)
- return ICERR_ERROR;
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
- if(EncodeMacroblockHighpass(pSC, pContext, iMBX, iMBY) != ICERR_OK)
- return ICERR_ERROR;
-
- if(iMBX + 1 == (int) pSC->cmbWidth && (iMBY + 1 == (int) pSC->cmbHeight ||
- (pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && iMBY == (int) pSC->WMISCP.uiTileY[pSC->cTileRow + 1] - 1)))
- { // end of a horizontal slice
- size_t k, l;
- // get sizes of each packet and update index table
- if (pSC->m_pNextSC == NULL || pSC->m_bSecondary) {
- for(k = 0; k < pSC->cNumBitIO; k ++){
- fillToByte(pSC->m_ppBitIO[k]);
- pSC->ppWStream[k]->GetPos(pSC->ppWStream[k], &l);
- pSC->pIndexTable[pSC->cNumBitIO * pSC->cTileRow + k] = l + getSizeWrite(pSC->m_ppBitIO[k]); // offset
- }
- }
-
- // reset coding contexts
- if(iMBY + 1 != (int) pSC->cmbHeight){
- for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++)
- ResetCodingContextEnc(&pSC->m_pCodingContext[k]);
- }
- }
- return ICERR_OK;
- }
- /*************************************************************************
- Top level function for processing a macroblock worth of input
- *************************************************************************/
- Int processMacroblock(CWMImageStrCodec *pSC)
- {
- Bool topORleft = (pSC->cColumn == 0 || pSC->cRow == 0);
- ERR_CODE result = ICERR_OK;
- size_t j, jend = (pSC->m_pNextSC != NULL);
- for (j = 0; j <= jend; j++) {
- transformMacroblock(pSC);
- if(!topORleft){
- getTilePos(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1);
- if(jend){
- pSC->m_pNextSC->cTileRow = pSC->cTileRow;
- pSC->m_pNextSC->cTileColumn = pSC->cTileColumn;
- }
- if ((result = encodeMB(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1)) != ICERR_OK)
- return result;
- }
- if (jend) {
- pSC->m_pNextSC->cRow = pSC->cRow;
- pSC->m_pNextSC->cColumn = pSC->cColumn;
- pSC = pSC->m_pNextSC;
- }
- }
- return ICERR_OK;
- }
- /*************************************************************************
- forwardRGBE: forward conversion from RGBE to RGB
- *************************************************************************/
- static _FORCEINLINE PixelI forwardRGBE (PixelI RGB, PixelI E)
- {
- PixelI iResult = 0, iAppend = 1;
- if (E == 0)
- return 0;
- assert (E!=0);
- E--;
- while (((RGB & 0x80) == 0) && (E > 0)) {
- RGB = (RGB << 1) + iAppend;
- iAppend = 0;
- E--;
- }
- // result will always be one of 3 cases
- // E RGB convert to
- // 0 [0.x] [0 x]
- // 0 [1.x] [1 x]
- // e [1.x] [e+1 x]
- if (E == 0) {
- iResult = RGB;
- }
- else {
- E++;
- iResult = (RGB & 0x7f) + (E << 7);
- }
- return iResult;
- }
- /*************************************************************************
- convert float-32 into float with (c, lm)!!
- *************************************************************************/
- static _FORCEINLINE PixelI float2pixel (float f, const char _c, const unsigned char _lm)
- {
- union uif
- {
- I32 i;
- float f;
- } x;
- PixelI _h, e, e1, m, s;
- if (f == 0)
- {
- _h = 0;
- }
- else
- {
- x.f = f;
- e = (x.i >> 23) & 0x000000ff;//here set e as e, not s! e includes s: [s e] 9 bits [31..23]
- m = (x.i & 0x007fffff) | 0x800000; // actual mantissa, with normalizer
- if (e == 0) { // denormal-land
- m ^= 0x800000; // actual mantissa, removing normalizer
- e++; // actual exponent -126
- }
- e1 = e - 127 + _c; // this is basically a division or quantization to a different exponent
- // note: _c cannot be greater than 127, so e1 cannot be greater than e
- //assert (_c <= 127);
- if (e1 <= 1) { // denormal-land
- if (e1 < 1)
- m >>= (1 - e1); // shift mantissa right to make exponent 1
- e1 = 1;
- if ((m & 0x800000) == 0) // if denormal, set e1 to zero else to 1
- e1 = 0;
- }
- m &= 0x007fffff;
- //for float-22:
- _h = (e1 << _lm) + ((m + (1 << (23 - _lm - 1))) >> (23 - _lm));//take 23-bit m, shift (23-lm), get lm-bit m for float22
- s = ((PixelI) x.i) >> 31;
- //padding to int-32:
- _h = (_h ^ s) - s;
- }
- return _h;
- }
- /*************************************************************************
- convert Half-16 to internal format, only need to handle sign bit
- *************************************************************************/
- static _FORCEINLINE PixelI forwardHalf (PixelI hHalf)
- {
- PixelI s;
- s = hHalf >> 31;
- hHalf = ((hHalf & 0x7fff) ^ s) - s;
- return hHalf;
- }
- //================================================================
- // Color Conversion
- // functions to get image data from input buffer
- // this inlcudes necessary color conversion and boundary padding
- //================================================================
- #define _CC(r, g, b) (b -= r, r += ((b + 1) >> 1) - g, g += ((r + 0) >> 1))
- #define _CC_CMYK(c, m, y, k) (y -= c, c += ((y + 1) >> 1) - m, m += (c >> 1) - k, k += ((m + 1) >> 1))
- //================================================================
- // BitIOInfo init/term for encoding
- const size_t MAX_MEMORY_SIZE_IN_WORDS = 64 << 20; // 1 << 20 \approx 1 million
- Int StrIOEncInit(CWMImageStrCodec* pSC)
- {
- pSC->m_param.bIndexTable = !(pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0);
- if(allocateBitIOInfo(pSC) != ICERR_OK){
- return ICERR_ERROR;
- }
- attachISWrite(pSC->pIOHeader, pSC->WMISCP.pWStream);
- if(pSC->cNumBitIO > 0){
- size_t i;
- #if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT
- TCHAR szPath[MAX_PATH];
- DWORD cSize, j, k;
- #endif
- char * pFilename;
- pSC->ppWStream = (struct WMPStream **)malloc(pSC->cNumBitIO * sizeof(struct WMPStream *));
- if(pSC->ppWStream == NULL) return ICERR_ERROR;
- memset(pSC->ppWStream, 0, pSC->cNumBitIO * sizeof(struct WMPStream *));
- if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) {
- #ifdef _WINDOWS_
- pSC->ppTempFile = (TCHAR **)malloc(pSC->cNumBitIO * sizeof(TCHAR *));
- if(pSC->ppTempFile == NULL) return ICERR_ERROR;
- memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(TCHAR *));
- #else
- pSC->ppTempFile = (char **)malloc(pSC->cNumBitIO * sizeof(char *));
- if(pSC->ppTempFile == NULL) return ICERR_ERROR;
- memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(char *));
- #endif
- }
- for(i = 0; i < pSC->cNumBitIO; i ++){
- if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) {
- #if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT
- Bool bUnicode = sizeof(TCHAR) == 2;
- pSC->ppTempFile[i] = (TCHAR *)malloc(MAX_PATH * sizeof(TCHAR));
- if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR;
- pFilename = (char *)pSC->ppTempFile[i];
- cSize = GetTempPath(MAX_PATH, szPath);
- if(cSize == 0 || cSize >= MAX_PATH)
- return ICERR_ERROR;
- if(!GetTempFileName(szPath, TEXT("wdp"), 0, pSC->ppTempFile[i]))
- return ICERR_ERROR;
- if(bUnicode){ // unicode file name
- for(k = j = cSize = 0; cSize < MAX_PATH; cSize ++, j += 2){
- if(pSC->ppTempFile[i][cSize] == '\0')
- break;
- if(pFilename[j] != '\0')
- pFilename[k ++] = pFilename[j];
- if(pFilename[j + 1] != '\0')
- pFilename[k ++] = pFilename[j + 1];
- }
- pFilename[cSize] = '\0';
- }
- #else //DPK needs to support ANSI
- pSC->ppTempFile[i] = (char *)malloc(FILENAME_MAX * sizeof(char));
- if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR;
- if ((pFilename = tmpnam(NULL)) == NULL)
- return ICERR_ERROR;
- strcpy(pSC->ppTempFile[i], pFilename);
- #endif
- if(CreateWS_File(pSC->ppWStream + i, pFilename, "w+b") != ICERR_OK) return ICERR_ERROR;
- }
- else {
- if(CreateWS_List(pSC->ppWStream + i) != ICERR_OK) return ICERR_ERROR;
- }
- attachISWrite(pSC->m_ppBitIO[i], pSC->ppWStream[i]);
- }
- }
- return ICERR_OK;
- }
- #define PUTBITS putBit16
- /*************************************************************************
- Write variable length byte aligned integer
- *************************************************************************/
- static Void PutVLWordEsc(BitIOInfo* pIO, Int iEscape, size_t s)
- {
- if (iEscape) {
- assert(iEscape <= 0xff && iEscape > 0xfc); // fd,fe,ff are the only valid escapes
- PUTBITS(pIO, iEscape, 8);
- }
- else if (s < 0xfb00) {
- PUTBITS(pIO, (U32) s, 16);
- }
- else {
- size_t t = s >> 16;
- if ((t >> 16) == 0) {
- PUTBITS(pIO, 0xfb, 8);
- }
- else {
- t >>= 16;
- PUTBITS(pIO, 0xfc, 8);
- PUTBITS(pIO, (U32)(t >> 16) & 0xffff, 16);
- PUTBITS(pIO, (U32) t & 0xffff, 16);
- }
- PUTBITS(pIO, (U32) t & 0xffff, 16);
- PUTBITS(pIO, (U32) s & 0xffff, 16);
- }
- }
- /*************************************************************************
- Write index table at start (null index table)
- *************************************************************************/
- Int writeIndexTableNull(CWMImageStrCodec * pSC)
- {
- if(pSC->cNumBitIO == 0){
- BitIOInfo* pIO = pSC->pIOHeader;
- fillToByte(pIO);
- /* Profile / Level info */
- PutVLWordEsc(pIO, 0, 4); // 4 bytes
- PUTBITS(pIO, 111, 8); // default profile idc
- PUTBITS(pIO, 255, 8); // default level idc
- PUTBITS(pIO, 1, 16); // LAST_FLAG
- }
- return ICERR_OK;
- }
- /*************************************************************************
- Write index table
- *************************************************************************/
- Int writeIndexTable(CWMImageStrCodec * pSC)
- {
- if(pSC->cNumBitIO > 0){
- BitIOInfo* pIO = pSC->pIOHeader;
- size_t *pTable = pSC->pIndexTable, iSize[4] = { 0 };
- I32 iEntry = (I32)pSC->cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1), i, k, l;
-
- // write index table header [0x0001] - 2 bytes
- PUTBITS(pIO, 1, 16);
- for(i = pSC->WMISCP.cNumOfSliceMinus1H; i>= 0 && pSC->bTileExtraction == FALSE; i --){
- for(k = 0; k < (int)pSC->cNumBitIO; ){
- for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, k ++)
- {
- if (i > 0)
- pTable[pSC->cNumBitIO * i + k] -= pSC->pIndexTable[pSC->cNumBitIO * (i - 1) + k]; // packet length
- iSize[l] += pTable[pSC->cNumBitIO * i + k];
- }
- }
- }
- iSize[3] = iSize[2] + iSize[1] + iSize[0];
- iSize[2] = iSize[1] + iSize[0];
- iSize[1] = iSize[0];
- iSize[0] = 0;
- for(i = 0; i < iEntry; ){
- for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, i ++)
- {
- writeIS_L1(pSC, pIO);
- PutVLWordEsc(pIO, (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0xff : 0, iSize[l]);
- iSize[l] += (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0 : pTable[i];
- }
- }
- writeIS_L1(pSC, pIO);
- PutVLWordEsc(pIO, 0xff, 0); // escape to end
- fillToByte(pIO);
- }
- return ICERR_OK;
- }
- Int copyTo(struct WMPStream * pSrc, struct WMPStream * pDst, size_t iBytes)
- {
- char pData[PACKETLENGTH];
- if (iBytes <= MINIMUM_PACKET_LENGTH){
- pSrc->Read(pSrc, pData, iBytes);
- return ICERR_OK;
- }
- while(iBytes > PACKETLENGTH){
- pSrc->Read(pSrc, pData, PACKETLENGTH);
- pDst->Write(pDst, pData, PACKETLENGTH);
- iBytes -= PACKETLENGTH;
- }
- pSrc->Read(pSrc, pData, iBytes);
- pDst->Write(pDst, pData, iBytes);
- return ICERR_OK;
- }
- Int StrIOEncTerm(CWMImageStrCodec* pSC)
- {
- BitIOInfo * pIO = pSC->pIOHeader;
- fillToByte(pIO);
- if(pSC->WMISCP.bVerbose){
- U32 i, j;
- printf("\n%d horizontal tiles:\n", pSC->WMISCP.cNumOfSliceMinus1H + 1);
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){
- printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileY[i]);
- }
- printf("\n%d vertical tiles:\n", pSC->WMISCP.cNumOfSliceMinus1V + 1);
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
- printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileX[i]);
- }
- if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
- printf("\nSpatial order bitstream\n");
- }
- else{
- printf("\nFrequency order bitstream\n");
- }
- if(!pSC->m_param.bIndexTable){
- printf("\nstreaming mode, no index table.\n");
- }
- else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
- for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
- printf("bitstream size for tile (%d, %d): %d.\n", j, i, (int) pSC->pIndexTable[j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i]);
- }
- }
- }
- else{
- for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
- size_t * p = &pSC->pIndexTable[(j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i) * 4];
- printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d %d.\n", j, i,
- (int) p[0], (int) p[1], (int) p[2], (int) p[3]);
- }
- }
- }
- }
-
- writeIndexTable(pSC); // write index table to the header
- detachISWrite(pSC, pIO);
- if(pSC->cNumBitIO > 0){
- size_t i, j, k, l;
- struct WMPStream * pDst = pSC->WMISCP.pWStream;
- size_t * pTable = pSC->pIndexTable;
- for(i = 0; i < pSC->cNumBitIO; i ++){
- detachISWrite(pSC, pSC->m_ppBitIO[i]);
- }
- for(i = 0; i < pSC->cNumBitIO; i ++){
- pSC->ppWStream[i]->SetPos(pSC->ppWStream[i], 0); // seek back for read
- }
- for(l = 0; l < (size_t)(pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++){
- for(i = 0, k = l; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){ // loop through tiles
- for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1V; j ++){
- if(pSC->WMISCP.bfBitstreamFormat == SPATIAL)
- copyTo(pSC->ppWStream[j], pDst, pTable[k ++]);
- else if (!pSC->WMISCP.bProgressiveMode){
- copyTo(pSC->ppWStream[j * pSC->cSB + 0], pDst, pTable[k ++]);
- if(pSC->cSB > 1)
- copyTo(pSC->ppWStream[j * pSC->cSB + 1], pDst, pTable[k ++]);
- if(pSC->cSB > 2)
- copyTo(pSC->ppWStream[j * pSC->cSB + 2], pDst, pTable[k ++]);
- if(pSC->cSB > 3)
- copyTo(pSC->ppWStream[j * pSC->cSB + 3], pDst, pTable[k ++]);
- }
- else{
- copyTo(pSC->ppWStream[j * pSC->cSB + l], pDst, pTable[k]);
- k += pSC->cSB;
- }
- }
- }
- }
- if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS){
- for(i = 0; i < pSC->cNumBitIO; i ++){
- if(pSC->ppWStream && pSC->ppWStream[i]){
- if((*(pSC->ppWStream + i))->state.file.pFile){
- fclose((*(pSC->ppWStream + i))->state.file.pFile);
- #ifdef _WINDOWS_
- if(DeleteFileA((LPCSTR)pSC->ppTempFile[i]) == 0)
- return ICERR_ERROR;
- #else
- if (remove(pSC->ppTempFile[i]) == -1)
- return ICERR_ERROR;
- #endif
- }
- if (*(pSC->ppWStream + i))
- free(*(pSC->ppWStream + i));
- }
- if(pSC->ppTempFile){
- if(pSC->ppTempFile[i])
- free(pSC->ppTempFile[i]);
- }
- }
- if(pSC->ppTempFile)
- free(pSC->ppTempFile);
- }
- else{
- for(i = 0; i < pSC->cNumBitIO; i ++){
- if(pSC->ppWStream && pSC->ppWStream[i])
- pSC->ppWStream[i]->Close(pSC->ppWStream + i);
- }
- }
- free(pSC->ppWStream);
- free(pSC->m_ppBitIO);
- free(pSC->pIndexTable);
- }
- return 0;
- }
- /*************************************************************************
- Write header of image plane
- *************************************************************************/
- Int WriteImagePlaneHeader(CWMImageStrCodec * pSC)
- {
- CWMImageInfo * pII = &pSC->WMII;
- CWMIStrCodecParam * pSCP = &pSC->WMISCP;
- BitIOInfo* pIO = pSC->pIOHeader;
- PUTBITS(pIO, (Int) pSC->m_param.cfColorFormat, 3); // internal color format
- PUTBITS(pIO, (Int) pSC->m_param.bScaledArith, 1); // lossless mode
- // subbands
- PUTBITS(pIO, (U32)pSCP->sbSubband, 4);
- // color parameters
- switch (pSC->m_param.cfColorFormat) {
- case YUV_420:
- case YUV_422:
- case YUV_444:
- PUTBITS(pIO, 0, 4);
- PUTBITS(pIO, 0, 4);
- break;
- case NCOMPONENT:
- PUTBITS(pIO, (Int) pSC->m_param.cNumChannels - 1, 4);
- PUTBITS(pIO, 0, 4);
- break;
- default:
- break;
- }
- // float and 32s additional parameters
- switch (pII->bdBitDepth) {
- case BD_16:
- case BD_16S:
- PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);
- break;
- case BD_32:
- case BD_32S:
- if(pSCP->nLenMantissaOrShift == 0)
- pSCP->nLenMantissaOrShift = 10;//default
- PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);
- break;
- case BD_32F:
- if(pSCP->nLenMantissaOrShift == 0)
- pSCP->nLenMantissaOrShift = 13;//default
- PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);//float conversion parameters
- PUTBITS(pIO, pSCP->nExpBias, 8);
- break;
- default:
- break;
- }
- // quantization
- PUTBITS(pIO, (pSC->m_param.uQPMode & 1) == 1 ? 0 : 1, 1); // DC frame uniform quantization?
- if((pSC->m_param.uQPMode & 1) == 0)
- writeQuantizer(pSC->pTile[0].pQuantizerDC, pIO, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0);
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY){
- PUTBITS(pIO, (pSC->m_param.uQPMode & 0x200) == 0 ? 1 : 0, 1); // use DC quantization?
- if((pSC->m_param.uQPMode & 0x200) != 0){
- PUTBITS(pIO, (pSC->m_param.uQPMode & 2) == 2 ? 0 : 1, 1); // LP frame uniform quantization?
- if((pSC->m_param.uQPMode & 2) == 0)
- writeQuantizer(pSC->pTile[0].pQuantizerLP, pIO, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0);
- }
- if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){
- PUTBITS(pIO, (pSC->m_param.uQPMode & 0x400) == 0 ? 1 : 0, 1); // use LP quantization?
- if((pSC->m_param.uQPMode & 0x400) != 0){
- PUTBITS(pIO, (pSC->m_param.uQPMode & 4) == 4 ? 0 : 1, 1); // HP frame uniform quantization?
- if((pSC->m_param.uQPMode & 4) == 0)
- writeQuantizer(pSC->pTile[0].pQuantizerHP, pIO, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0);
- }
- }
- }
- fillToByte(pIO); // remove this later
- return ICERR_OK;
- }
- /*************************************************************************
- Write header to buffer
- *************************************************************************/
- Int WriteWMIHeader(CWMImageStrCodec * pSC)
- {
- CWMImageInfo * pII = &pSC->WMII;
- CWMIStrCodecParam * pSCP = &pSC->WMISCP;
- CCoreParameters * pCoreParam = &pSC->m_param;
- BitIOInfo* pIO = pSC->pIOHeader;
- U32 /*iSizeOfSize = 2,*/ i;
- // temporary assignments / reserved words
- // const Int HEADERSIZE = 0;
- Bool bInscribed = FALSE;
- Bool bAbbreviatedHeader = (((pII->cWidth + 15) / 16 > 255 || (pII->cHeight + 15) / 16 > 255) ? FALSE : TRUE);
- if(pCoreParam->bTranscode == FALSE)
- pCoreParam->cExtraPixelsTop = pCoreParam->cExtraPixelsLeft = pCoreParam->cExtraPixelsRight = pCoreParam->cExtraPixelsBottom = 0;
- // num of extra boundary pixels due to compressed domain processing
- bInscribed = (pCoreParam->cExtraPixelsTop || pCoreParam->cExtraPixelsLeft || pCoreParam->cExtraPixelsBottom || pCoreParam->cExtraPixelsRight);
- // 0
- /** signature **/
- for (i = 0; i < 8; PUTBITS(pSC->pIOHeader, gGDISignature[i++], 8));
- // 8
- /** codec version and subversion **/
- PUTBITS(pIO, CODEC_VERSION, 4); // this should be changed to "profile" in RTM
- if (pSC->WMISCP.bUseHardTileBoundaries)
- PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_HARD_TILES, 4);
- else
- PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_SOFT_TILES, 4);
- // 9 primary parameters
- PUTBITS(pIO, (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) ? 1 : 0, 1); // tiling present
- PUTBITS(pIO, (Int) pSCP->bfBitstreamFormat, 1); // bitstream layout
- PUTBITS(pIO, pII->oOrientation, 3); // m_iRotateFlip
- PUTBITS(pIO, pSC->m_param.bIndexTable, 1); // index table present
- PUTBITS(pIO, pSCP->olOverlap, 2); // overlap
- // 10
- PUTBITS(pIO, bAbbreviatedHeader, 1); // short words for size and tiles
- PUTBITS(pIO, 1, 1); // long word length (use intelligence later)
- PUTBITS(pIO, bInscribed, 1); // windowing
- PUTBITS(pIO, pSC->m_param.bTrimFlexbitsFlag, 1); // trim flexbits flag sent
- PUTBITS(pIO, 0, 1); // tile stretching parameters (not enabled)
- PUTBITS(pIO, 0, 2); // reserved bits
- PUTBITS(pIO, (Int) pSC->m_param.bAlphaChannel, 1); // alpha channel present
- // 11 - informational
- PUTBITS(pIO, (Int) pII->cfColorFormat, 4); // source color format
- if(BD_1 == pII->bdBitDepth && pSCP->bBlackWhite)
- PUTBITS(pIO, (Int) BD_1alt, 4); // source bit depth
- else
- PUTBITS(pIO, (Int) pII->bdBitDepth, 4); // source bit depth
- // 12 - Variable length fields
- // size
- putBit32(pIO, (U32)(pII->cWidth - 1), bAbbreviatedHeader ? 16 : 32);
- putBit32(pIO, (U32)(pII->cHeight - 1), bAbbreviatedHeader ? 16 : 32);
- // tiling
- if (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) {
- PUTBITS(pIO, pSCP->cNumOfSliceMinus1V, LOG_MAX_TILES); // # of vertical slices
- PUTBITS(pIO, pSCP->cNumOfSliceMinus1H, LOG_MAX_TILES); // # of horizontal slices
- }
- // tile sizes
- for(i = 0; i < pSCP->cNumOfSliceMinus1V; i ++){ // width in MB of vertical slices, not needed for last slice!
- PUTBITS(pIO, pSCP->uiTileX[i + 1] - pSCP->uiTileX[i], bAbbreviatedHeader ? 8 : 16);
- }
- for(i = 0; i < pSCP->cNumOfSliceMinus1H; i ++){ // width in MB of horizontal slices, not needed for last slice!
- PUTBITS(pIO, pSCP->uiTileY[i + 1] - pSCP->uiTileY[i], bAbbreviatedHeader ? 8 : 16);
- }
- // window due to compressed domain processing
- if (bInscribed) {
- PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsTop, 6);
- PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsLeft, 6);
- PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsBottom, 6);
- PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsRight, 6);
- }
- fillToByte(pIO); // redundant
- // write image plane headers
- WriteImagePlaneHeader(pSC);
- return ICERR_OK;
- }
- // streaming codec init/term
- Int StrEncInit(CWMImageStrCodec* pSC)
- {
- COLORFORMAT cf = pSC->m_param.cfColorFormat;
- COLORFORMAT cfE = pSC->WMII.cfColorFormat;
- U16 iQPIndexY = 0, iQPIndexYLP = 0, iQPIndexYHP = 0;
- U16 iQPIndexU = 0, iQPIndexULP = 0, iQPIndexUHP = 0;
- U16 iQPIndexV = 0, iQPIndexVLP = 0, iQPIndexVHP = 0;
- size_t i;
- Bool b32bit = sizeof(size_t) == 4;
- /** color transcoding with resolution change **/
- pSC->m_bUVResolutionChange = (((cfE == CF_RGB || cfE == YUV_444 || cfE == CMYK || cfE == CF_RGBE) &&
- (cf == YUV_422 || cf == YUV_420))
- || (cfE == YUV_422 && cf == YUV_420)) && !pSC->WMISCP.bYUVData;
- if(pSC->m_bUVResolutionChange){
- size_t cSize = ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0)) * pSC->cmbWidth + 256;
- if(b32bit){ // integer overlow/underflow check for 32-bit system
- if(((pSC->cmbWidth >> 16) * ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0))) & 0xffff0000)
- return ICERR_ERROR;
- if(cSize >= 0x3fffffff)
- return ICERR_ERROR;
- }
- pSC->pResU = (PixelI *)malloc(cSize * sizeof(PixelI));
- pSC->pResV = (PixelI *)malloc(cSize * sizeof(PixelI));
- if(pSC->pResU == NULL || pSC->pResV == NULL){
- return ICERR_ERROR;
- }
- }
- pSC->cTileColumn = pSC->cTileRow = 0;
- if(allocateTileInfo(pSC) != ICERR_OK)
- return ICERR_ERROR;
- if(pSC->m_param.bTranscode == FALSE){
- pSC->m_param.uQPMode = 0x150; // 101010 000
- // 000 == uniform (not per tile) DC, LP, HP
- // 101010 == cChMode == 2 == independent (not same) DC, LP, HP
- /** lossless or Y component lossless condition: all subbands present, uniform quantization with QPIndex 1 **/
- pSC->m_param.bScaledArith = !((pSC->m_param.uQPMode & 7) == 0 &&
- 1 == pSC->WMISCP.uiDefaultQPIndex <= 1 &&
- pSC->WMISCP.sbSubband == SB_ALL &&
- pSC->m_bUVResolutionChange == FALSE) &&
- !pSC->WMISCP.bUnscaledArith;
- if (BD_32 == pSC->WMII.bdBitDepth || BD_32S == pSC->WMII.bdBitDepth || BD_32F == pSC->WMII.bdBitDepth) {
- pSC->m_param.bScaledArith = FALSE;
- }
- pSC->m_param.uQPMode |= 0x600; // don't use DC QP for LP, LP QP for HP
- // default QPs
- iQPIndexY = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1?
- pSC->WMISCP.uiDefaultQPIndexAlpha : pSC->WMISCP.uiDefaultQPIndex;
- // determine the U,V index
- iQPIndexU = pSC->WMISCP.uiDefaultQPIndexU!=0?
- pSC->WMISCP.uiDefaultQPIndexU: iQPIndexY;
- iQPIndexV = pSC->WMISCP.uiDefaultQPIndexV!=0?
- pSC->WMISCP.uiDefaultQPIndexV: iQPIndexY;
- // determine the QPIndexYLP
- iQPIndexYLP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ?
- pSC->WMISCP.uiDefaultQPIndexAlpha :
- (pSC->WMISCP.uiDefaultQPIndexYLP == 0 ?
- pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYLP); // default to QPIndex if not set
- // determine the QPIndexYHP
- iQPIndexYHP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ?
- pSC->WMISCP.uiDefaultQPIndexAlpha :
- (pSC->WMISCP.uiDefaultQPIndexYHP == 0 ?
- pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYHP); // default to QPIndex if not set
- // determine the U,V LP index
- iQPIndexULP = pSC->WMISCP.uiDefaultQPIndexULP!=0?
- pSC->WMISCP.uiDefaultQPIndexULP: iQPIndexU;
- iQPIndexVLP = pSC->WMISCP.uiDefaultQPIndexVLP!=0?
- pSC->WMISCP.uiDefaultQPIndexVLP: iQPIndexV;
- // determine the U,V HP index
- iQPIndexUHP = pSC->WMISCP.uiDefaultQPIndexUHP!=0?
- pSC->WMISCP.uiDefaultQPIndexUHP: iQPIndexU;
- iQPIndexVHP = pSC->WMISCP.uiDefaultQPIndexVHP!=0?
- pSC->WMISCP.uiDefaultQPIndexVHP: iQPIndexV;
- // clamp the QPIndex - 0 is lossless mode
- if(iQPIndexY < 2)
- iQPIndexY = 0;
- if (iQPIndexYLP < 2)
- iQPIndexYLP = 0;
- if (iQPIndexYHP < 2)
- iQPIndexYHP = 0;
- if(iQPIndexU < 2)
- iQPIndexU = 0;
- if (iQPIndexULP < 2)
- iQPIndexULP = 0;
- if (iQPIndexUHP < 2)
- iQPIndexUHP = 0;
- if(iQPIndexV < 2)
- iQPIndexV = 0;
- if (iQPIndexVLP < 2)
- iQPIndexVLP = 0;
- if (iQPIndexVHP < 2)
- iQPIndexVHP = 0;
- }
- if((pSC->m_param.uQPMode & 1) == 0){ // DC frame uniform quantization
- if(allocateQuantizer(pSC->pTile[0].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
- return ICERR_ERROR;
- setUniformQuantizer(pSC, 0);
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- if(pSC->m_param.bTranscode)
- pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i];
- else
- pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i] = (U8)(((i == 0 ? iQPIndexY : (i == 1) ? iQPIndexU: iQPIndexV)) & 0xff);
- formatQuantizer(pSC->pTile[0].pQuantizerDC, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- pSC->pTile[0].pQuantizerDC[i]->iOffset = (pSC->pTile[0].pQuantizerDC[i]->iQP >> 1);
- }
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY){
- if((pSC->m_param.uQPMode & 2) == 0){ // LP frame uniform quantization
- if(allocateQuantizer(pSC->pTile[0].pQuantizerLP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
- return ICERR_ERROR;
- setUniformQuantizer(pSC, 1);
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- if(pSC->m_param.bTranscode)
- pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i];
- else
- pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i] = (U8)(((i == 0 ? iQPIndexYLP : (i == 1) ? iQPIndexULP: iQPIndexVLP)) & 0xff);
- formatQuantizer(pSC->pTile[0].pQuantizerLP, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
- }
- if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){
- if((pSC->m_param.uQPMode & 4) == 0){ // HP frame uniform quantization
- if(allocateQuantizer(pSC->pTile[0].pQuantizerHP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
- return ICERR_ERROR;
- setUniformQuantizer(pSC, 2);
- for(i = 0; i < pSC->m_param.cNumChannels; i ++)
- if(pSC->m_param.bTranscode)
- pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i];
- else
- pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i] = (U8)(((i == 0 ? iQPIndexYHP : (i == 1) ? iQPIndexUHP: iQPIndexVHP)) & 0xff);
- formatQuantizer(pSC->pTile[0].pQuantizerHP, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0, FALSE, pSC->m_param.bScaledArith);
- }
- }
- }
- if(allocatePredInfo(pSC) != ICERR_OK){
- return ICERR_ERROR;
- }
- if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES || AllocateCodingContextEnc (pSC, pSC->WMISCP.cNumOfSliceMinus1V + 1, pSC->WMISCP.uiTrimFlexBits) != ICERR_OK){
- return ICERR_ERROR;
- }
-
- if (pSC->m_bSecondary) {
- pSC->pIOHeader = pSC->m_pNextSC->pIOHeader;
- pSC->m_ppBitIO = pSC->m_pNextSC->m_ppBitIO;
- pSC->cNumBitIO = pSC->m_pNextSC->cNumBitIO;
- pSC->cSB = pSC->m_pNextSC->cSB;
- pSC->ppWStream = pSC->m_pNextSC->ppWStream;
- pSC->pIndexTable = pSC->m_pNextSC->pIndexTable;
- setBitIOPointers(pSC);
- }
- else {
- StrIOEncInit(pSC);
- setBitIOPointers(pSC);
- WriteWMIHeader(pSC);
- }
- return ICERR_OK;
- }
- static Int StrEncTerm(CTXSTRCODEC ctxSC)
- {
- CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
- size_t j, jend = (pSC->m_pNextSC != NULL);
- for (j = 0; j <= jend; j++) {
- if (sizeof(*pSC) != pSC->cbStruct) {
- return ICERR_ERROR;
- }
- if(pSC->m_bUVResolutionChange){
- if(pSC->pResU != NULL)
- free(pSC->pResU);
- if(pSC->pResV != NULL)
- free(pSC->pResV);
- }
- freePredInfo(pSC);
- if (j == 0)
- StrIOEncTerm(pSC);
- FreeCodingContextEnc(pSC);
-
- freeTileInfo(pSC);
- pSC->WMISCP.nExpBias -= 128; // reset
- pSC = pSC->m_pNextSC;
- }
- return 0;
- }
- U32 setUniformTiling(U32 * pTile, U32 cNumTile, U32 cNumMB)
- {
- U32 i, j;
- while((cNumMB + cNumTile - 1) / cNumTile > 65535) // too few tiles
- cNumTile ++;
- for(i = cNumTile, j = cNumMB; i > 1; i --){
- pTile[cNumTile - i] = (j + i - 1) / i;
- j -= pTile[cNumTile - i];
- }
- return cNumTile;
- }
- U32 validateTiling(U32 * pTile, U32 cNumTile, U32 cNumMB)
- {
- U32 i, cMBs;
- if(cNumTile == 0)
- cNumTile = 1;
- if(cNumTile > cNumMB) // too many tiles
- cNumTile = 1;
- if(cNumTile > MAX_TILES)
- cNumTile = MAX_TILES;
- for(i = cMBs = 0; i + 1 < cNumTile; i ++){
- if(pTile[i] == 0 || pTile[i] > 65535){ // invalid tile setting, resetting to uniform tiling
- cNumTile = setUniformTiling(pTile, cNumTile, cNumMB);
- break;
- }
-
- cMBs += pTile[i];
- if(cMBs >= cNumMB){
- cNumTile = i + 1;
- break;
- }
- }
- // last tile
- if(cNumMB - cMBs > 65536)
- cNumTile = setUniformTiling(pTile, cNumTile, cNumMB);
- for(i = 1; i < cNumTile; i ++)
- pTile[i] += pTile[i - 1];
- for(i = cNumTile - 1; i > 0; i --)
- pTile[i] = pTile[i - 1];
- pTile[0] = 0;
- return cNumTile;
- }
- /*************************************************************************
- Validate and adjust input params here
- *************************************************************************/
- Int ValidateArgs(CWMImageInfo* pII, CWMIStrCodecParam *pSCP)
- {
- int i;
- Bool bTooNarrowTile = FALSE;
- if(pII->cWidth > (1 << 28) || pII->cHeight > (1 << 28) || pII->cWidth == 0 || pII->cHeight == 0){
- printf("Unsurpported image size!\n");
- return ICERR_ERROR; // unsurpported image size
- }
- if (((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO) && ((Int)(((U32)pII->cWidth + 15) >> 4) < 2)) {
- printf("Image width must be at least 2 MB wide for subsampled chroma and two levels of overlap!\n");
- return ICERR_ERROR;
- }
- if(pSCP->sbSubband == SB_ISOLATED || pSCP->sbSubband >= SB_MAX) // not allowed
- pSCP->sbSubband = SB_ALL;
- if(pII->bdBitDepth == BD_5 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){
- printf("Unsupported BD_5 image format!\n");
- return ICERR_ERROR; // BD_5 must be compact RGB!
- }
- if(pII->bdBitDepth == BD_565 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){
- printf("Unsupported BD_565 image format!\n");
- return ICERR_ERROR; // BD_5 must be compact RGB!
- }
- if(pII->bdBitDepth == BD_10 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 32 || pII->cLeadingPadding != 0)){
- printf("Unsupported BD_10 image format!\n");
- return ICERR_ERROR; // BD_10 must be compact RGB!
- }
- if((pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_565 || pII->bdBitDepth == BD_10) &&
- (pSCP->cfColorFormat != YUV_420 && pSCP->cfColorFormat != YUV_422 && pSCP->cfColorFormat != Y_ONLY))
- pSCP->cfColorFormat = YUV_444;
- if(BD_1 == pII->bdBitDepth){ // binary image
- if(pII->cfColorFormat != Y_ONLY){
- printf("BD_1 image must be black-and white!\n");
- return ICERR_ERROR;
- }
- pSCP->cfColorFormat = Y_ONLY; // can only be black white
- }
- if(pSCP->bdBitDepth != BD_LONG)
- pSCP->bdBitDepth = BD_LONG; // currently only support 32 bit internally
- if(pSCP->uAlphaMode > 1 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == YUV_422
- || pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10
- || pII->bdBitDepth == BD_1))
- {
- printf("Alpha is not supported for this pixel format!\n");
- return ICERR_ERROR;
- }
- if((pSCP->cfColorFormat == YUV_420 || pSCP->cfColorFormat == YUV_422) && (pII->bdBitDepth == BD_16F || pII->bdBitDepth == BD_32F || pII->cfColorFormat == CF_RGBE))
- {
- printf("Float or RGBE images must be encoded with YUV 444!\n");
- return ICERR_ERROR;
- }
- // adjust tiling
- pSCP->cNumOfSliceMinus1V = validateTiling(pSCP->uiTileX, pSCP->cNumOfSliceMinus1V + 1, (((U32)pII->cWidth + 15) >> 4)) - 1;
- pSCP->cNumOfSliceMinus1H = validateTiling(pSCP->uiTileY, pSCP->cNumOfSliceMinus1H + 1, (((U32)pII->cHeight + 15) >> 4)) - 1;
- if (pSCP->bUseHardTileBoundaries && ((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO)) {
- for (i = 1; i < (int) (pSCP->cNumOfSliceMinus1H + 1); i++) {
- if ((Int)(pSCP->uiTileY[i] - pSCP->uiTileY[i - 1]) < 2) {
- bTooNarrowTile = TRUE;
- break;
- }
- }
- if ((Int)((((U32)pII->cWidth + 15) >> 4) - pSCP->uiTileY[pSCP->cNumOfSliceMinus1H]) < 2)
- bTooNarrowTile = TRUE;
- }
- if (bTooNarrowTile) {
- printf("Tile width must be at least 2 MB wide for hard tiles, subsampled chroma, and two levels of overlap!\n");
- return ICERR_ERROR;
- }
- if(pSCP->cChannel > MAX_CHANNELS)
- return ICERR_ERROR;
- /** supported color transcoding **/
- /** ARGB, RGB => YUV_444, YUV_422, YUV_420, Y_ONLY **/
- /** YUV_444 => YUV_422, YUV_420, Y_ONLY **/
- /** YUV_422 => YUV_420, Y_ONLY **/
- /** YUV_420 => Y_ONLY **/
- /** unsupported color transcoding **/
- /** Y_ONLY, YUV_420, YUV_422 => YUV_444 **/
- /** Y_ONLY, YUV_420 => YUV_422 **/
- /** Y_ONLY => YUV_420 **/
- if((pII->cfColorFormat == Y_ONLY && pSCP->cfColorFormat != Y_ONLY) ||
- (pSCP->cfColorFormat == YUV_422 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY)) ||
- (pSCP->cfColorFormat == YUV_444 && (pII->cfColorFormat == YUV_422 || pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY))){
- pSCP->cfColorFormat = pII->cfColorFormat; // force not to do color transcoding!
- }
- else if (pII->cfColorFormat == NCOMPONENT) {
- pSCP->cfColorFormat = NCOMPONENT; // force not to do color transcoding!
- }
- if (CMYK == pII->cfColorFormat && pSCP->cfColorFormat == NCOMPONENT)
- {
- pSCP->cfColorFormat = CMYK;
- }
- if(pSCP->cfColorFormat != NCOMPONENT){
- if(pSCP->cfColorFormat == Y_ONLY)
- pSCP->cChannel = 1;
- else if(pSCP->cfColorFormat == CMYK)
- pSCP->cChannel = 4;
- else
- pSCP->cChannel = 3;
- }
- if(pSCP->sbSubband >= SB_MAX)
- pSCP->sbSubband = SB_ALL;
- pII->cChromaCenteringX = 0;
- pII->cChromaCenteringY = 0;
- return ICERR_OK;
- }
- /*************************************************************************
- Initialization of CWMImageStrCodec struct
- *************************************************************************/
- static Void InitializeStrEnc(CWMImageStrCodec *pSC,
- const CWMImageInfo* pII, const CWMIStrCodecParam *pSCP)
- {
- pSC->cbStruct = sizeof(*pSC);
- pSC->WMII = *pII;
- pSC->WMISCP = *pSCP;
- // set nExpBias
- if (pSC->WMISCP.nExpBias == 0)
- pSC->WMISCP.nExpBias = 4 + 128;//default
- pSC->WMISCP.nExpBias += 128; // rollover arithmetic
- pSC->cRow = 0;
- pSC->cColumn = 0;
-
- pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16;
- pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16;
- pSC->Load = inputMBRow;
- pSC->Quantize = quantizeMacroblock;
- pSC->ProcessTopLeft = processMacroblock;
- pSC->ProcessTop = processMacroblock;
- pSC->ProcessTopRight = processMacroblock;
- pSC->ProcessLeft = processMacroblock;
- pSC->ProcessCenter = processMacroblock;
- pSC->ProcessRight = processMacroblock;
- pSC->ProcessBottomLeft = processMacroblock;
- pSC->ProcessBottom = processMacroblock;
- pSC->ProcessBottomRight = processMacroblock;
- pSC->m_pNextSC = NULL;
- pSC->m_bSecondary = FALSE;
- }
- /*************************************************************************
- Streaming API init
- *************************************************************************/
- Int ImageStrEncInit(
- CWMImageInfo* pII,
- CWMIStrCodecParam *pSCP,
- CTXSTRCODEC* pctxSC)
- {
- static size_t cbChannels[BD_MAX] = {2, 4};
- size_t cbChannel = 0, cblkChroma = 0, i;
- size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0;
- CWMImageStrCodec* pSC = NULL, *pNextSC = NULL;
- char* pb = NULL;
- size_t cb = 0;
- Bool b32bit = sizeof(size_t) == 4;
- Int err;
- if(ValidateArgs(pII, pSCP) != ICERR_OK){
- goto ErrorExit;
- }
- //================================================
- *pctxSC = NULL;
- //================================================
- cbChannel = cbChannels[pSCP->bdBitDepth];
- cblkChroma = cblkChromas[pSCP->cfColorFormat];
- cbMacBlockStride = cbChannel * 16 * 16;
- cbMacBlockChroma = cbChannel * 16 * cblkChroma;
- cMacBlock = (pII->cWidth + 15) / 16;
- //================================================
- cb = sizeof(*pSC) + (128 - 1) + (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader);
- i = cbMacBlockStride + cbMacBlockChroma * (pSCP->cChannel - 1);
- if(b32bit) // integer overlow/underflow check for 32-bit system
- if(((cMacBlock >> 15) * i) & 0xffff0000)
- return ICERR_ERROR;
- i *= cMacBlock * 2;
- cb += i;
- pb = malloc(cb);
- if (NULL == pb)
- {
- goto ErrorExit;
- }
- memset(pb, 0, cb);
- //================================================
- pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC);
- // Set up perf timers
- PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf);
- PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf);
- PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf);
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf);
- pSC->m_param.cfColorFormat = pSCP->cfColorFormat;
- pSC->m_param.bAlphaChannel = (pSCP->uAlphaMode == 3);
- pSC->m_param.cNumChannels = pSCP->cChannel;
- pSC->m_param.cExtraPixelsTop = pSC->m_param.cExtraPixelsBottom
- = pSC->m_param.cExtraPixelsLeft = pSC->m_param.cExtraPixelsRight = 0;
- pSC->cbChannel = cbChannel;
- pSC->m_param.bTranscode = pSC->bTileExtraction = FALSE;
- //================================================
- InitializeStrEnc(pSC, pII, pSCP);
- //================================================
- // 2 Macro Row buffers for each channel
- pb = ALIGNUP(pb, 128);
- for (i = 0; i < pSC->m_param.cNumChannels; i++) {
- pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
- pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
- cbMacBlockStride = cbMacBlockChroma;
- }
- //================================================
- // lay 2 aligned IO buffers just below pIO struct
- pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
- pSC->pIOHeader = (BitIOInfo*)pb;
- //================================================
- err = StrEncInit(pSC);
- if (ICERR_OK != err)
- goto ErrorExit;
- // if interleaved alpha is needed
- if (pSC->m_param.bAlphaChannel) {
- cbMacBlockStride = cbChannel * 16 * 16;
- // 1. allocate new pNextSC info
- //================================================
- cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2;
- pb = malloc(cb);
- if (NULL == pb)
- {
- goto ErrorExit;
- }
- memset(pb, 0, cb);
- //================================================
- pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC);
- // 2. initialize pNextSC
- pNextSC->m_param.cfColorFormat = Y_ONLY;
- pNextSC->m_param.cNumChannels = 1;
- pNextSC->m_param.bAlphaChannel = TRUE;
- pNextSC->cbChannel = cbChannel;
- //================================================
- // 3. initialize arrays
- InitializeStrEnc(pNextSC, pII, pSCP);
- //================================================
- // 2 Macro Row buffers for each channel
- pb = ALIGNUP(pb, 128);
- pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
- pNextSC->a1MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
- //================================================
- pNextSC->pIOHeader = pSC->pIOHeader;
- //================================================
- // 4. link pSC->pNextSC = pNextSC
- pNextSC->m_pNextSC = pSC;
- pNextSC->m_bSecondary = TRUE;
- // 5. StrEncInit
- StrEncInit(pNextSC);
- // 6. Write header of image plane
- WriteImagePlaneHeader(pNextSC);
- }
- pSC->m_pNextSC = pNextSC;
- //================================================
- *pctxSC = (CTXSTRCODEC)pSC;
- writeIndexTableNull(pSC);
- #if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC)
- StrEncOpt(pSC);
- #endif // OPT defined
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- return ICERR_OK;
- ErrorExit:
- return ICERR_ERROR;
- }
- /*************************************************************************
- Streaming API encode
- *************************************************************************/
- Int ImageStrEncEncode(
- CTXSTRCODEC ctxSC,
- const CWMImageBufferInfo* pBI)
- {
- CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
- CWMImageStrCodec* pNextSC = pSC->m_pNextSC;
- ImageDataProc ProcessLeft, ProcessCenter, ProcessRight;
- if (sizeof(*pSC) != pSC->cbStruct)
- {
- return ICERR_ERROR;
- }
- //================================
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- pSC->WMIBI = *pBI;
- pSC->cColumn = 0;
- initMRPtr(pSC);
- if (pNextSC)
- pNextSC->WMIBI = *pBI;
- if (0 == pSC->cRow) {
- ProcessLeft = pSC->ProcessTopLeft;
- ProcessCenter = pSC->ProcessTop;
- ProcessRight = pSC->ProcessTopRight;
- }
- else {
- ProcessLeft = pSC->ProcessLeft;
- ProcessCenter = pSC->ProcessCenter;
- ProcessRight = pSC->ProcessRight;
- }
- if( pSC->Load(pSC) != ICERR_OK )
- return ICERR_ERROR;
- if(ProcessLeft(pSC) != ICERR_OK)
- return ICERR_ERROR;
- advanceMRPtr(pSC);
- //================================
- for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) {
- if(ProcessCenter(pSC) != ICERR_OK)
- return ICERR_ERROR;
- advanceMRPtr(pSC);
- }
- //================================
- if(ProcessRight(pSC) != ICERR_OK)
- return ICERR_ERROR;
- if (pSC->cRow)
- advanceOneMBRow(pSC);
- ++pSC->cRow;
- swapMRPtr(pSC);
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- return ICERR_OK;
- }
- /*************************************************************************
- Streaming API term
- *************************************************************************/
- Int ImageStrEncTerm(
- CTXSTRCODEC ctxSC)
- {
- CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
- // CWMImageStrCodec *pNextSC = pSC->m_pNextSC;
- if (sizeof(*pSC) != pSC->cbStruct)
- {
- return ICERR_ERROR;
- }
- //================================
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- pSC->cColumn = 0;
- initMRPtr(pSC);
- pSC->ProcessBottomLeft(pSC);
- advanceMRPtr(pSC);
- //================================
- for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) {
- pSC->ProcessBottom(pSC);
- advanceMRPtr(pSC);
- }
- //================================
- pSC->ProcessBottomRight(pSC);
- //================================
- StrEncTerm(pSC);
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
- PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC);
- PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
- free(pSC);
- return ICERR_OK;
- }
- // centralized UV downsampling
- #define DF_ODD ((((d1 + d2 + d3) << 2) + (d2 << 1) + d0 + d4 + 8) >> 4)
- Void downsampleUV(CWMImageStrCodec * pSC)
- {
- const COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
- const COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
- PixelI * pSrc, * pDst;
- PixelI d0, d1, d2, d3, d4;
- size_t iChannel, iRow, iColumn;
- for(iChannel = 1; iChannel < 3; iChannel ++){
- if(cfExt != YUV_422){ // need to do horizontal downsampling, 444 => 422
- const size_t cShift = (cfInt == YUV_422 ? 1 : 0);
- pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV);
- pDst = (cfInt == YUV_422 ? pSC->p1MBbuffer[iChannel] : pSrc);
-
- for(iRow = 0; iRow < 16; iRow ++){
- d0 = d4 = pSrc[idxCC[iRow][2]], d1 = d3 = pSrc[idxCC[iRow][1]], d2 = pSrc[idxCC[iRow][0]]; // left boundary
-
- for(iColumn = 0; iColumn + 2 < pSC->cmbWidth * 16; iColumn += 2){
- pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD;
- d0 = d2, d1 = d3, d2 = d4;
- d3 = pSrc[(((iColumn + 3) >> 4) << 8) + idxCC[iRow][(iColumn + 3) & 0xf]];
- d4 = pSrc[(((iColumn + 4) >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 0xf]];
- }
- d4 = d2; // right boundary
- pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD;
- }
- }
- if(cfInt == YUV_420){ // need to do vertical downsampling
- const size_t cShift = (cfExt == YUV_422 ? 0 : 1);
- PixelI * pBuf[4];
- size_t mbOff, pxOff;
-
- pDst = pSC->p1MBbuffer[iChannel];
- pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV);
- pBuf[0] = pSrc + (pSC->cmbWidth << (cfExt == YUV_422 ? 7 : 8));
- pBuf[1] = pBuf[0] + pSC->cmbWidth * 8, pBuf[2] = pBuf[1] + pSC->cmbWidth * 8, pBuf[3] = pBuf[2] + pSC->cmbWidth * 8;
- for(iColumn = 0; iColumn < pSC->cmbWidth * 8; iColumn ++){
- mbOff = (iColumn >> 3) << (7 + cShift);
- pxOff = (iColumn & 7) << cShift;
- if(pSC->cRow == 0) // top image boundary
- d0 = d4 = pSrc[mbOff + idxCC[2][pxOff]], d1 = d3 = pSrc[mbOff + idxCC[1][pxOff]], d2 = pSrc[mbOff + idxCC[0][pxOff]]; // top MB boundary
- else{
- // last row of previous MB row
- d0 = pBuf[0][iColumn], d1 = pBuf[1][iColumn], d2 = pBuf[2][iColumn], d3 = pBuf[3][iColumn], d4 = pSrc[mbOff + idxCC[0][pxOff]];
- pSC->p0MBbuffer[iChannel][((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD;
- // for first row of current MB
- d0 = pBuf[2][iColumn], d1 = pBuf[3][iColumn];
- d2 = pSrc[mbOff + idxCC[0][pxOff]], d3 = pSrc[mbOff + idxCC[1][pxOff]], d4 = pSrc[mbOff + idxCC[2][pxOff]];
- }
- for(iRow = 0; iRow < 12; iRow += 2){
- pDst[((iColumn >> 3) << 6) + idxCC_420[iRow >> 1][iColumn & 7]] = DF_ODD;
- d0 = d2, d1 = d3, d2 = d4;
- d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]];
- d4 = pSrc[mbOff + idxCC[iRow + 4][pxOff]];
- }
-
- //last row of current MB
- pDst[((iColumn >> 3) << 6) + idxCC_420[6][iColumn & 7]] = DF_ODD;
- d0 = d2, d1 = d3, d2 = d4;
- d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]];
- if(pSC->cRow + 1 == pSC->cmbHeight){ // bottom image boundary
- d4 = d2;
- pDst[((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD;
- }
- else{
- for(iRow = 0; iRow < 4; iRow ++)
- pBuf[iRow][iColumn] = pSrc[mbOff + idxCC[iRow + 12][pxOff]];
- }
- }
- }
- }
- }
- // centralized horizontal padding
- Void padHorizontally(CWMImageStrCodec * pSC)
- {
- if(pSC->WMII.cWidth != pSC->cmbWidth * 16){ // horizontal padding is necessary!
- const COLORFORMAT cfExt = pSC->WMISCP.bYUVData ?
- pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat;
- size_t cFullChannel = pSC->WMISCP.cChannel;
- size_t iLast = pSC->WMII.cWidth - 1;
- PixelI * pCh[16];
- size_t iChannel, iColumn, iRow;
- if(cfExt == YUV_420 || cfExt == YUV_422 || cfExt == Y_ONLY)
- cFullChannel = 1;
- assert(cFullChannel <= 16);
- assert(pSC->WMISCP.cChannel <= 16);
- for(iChannel = 0; iChannel < pSC->WMISCP.cChannel; iChannel ++)
- pCh[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
- if(pSC->m_bUVResolutionChange)
- pCh[1] = pSC->pResU, pCh[2] = pSC->pResV;
- // pad full resoluton channels
- for(iRow = 0; iRow < 16; iRow ++){
- const size_t iPosLast = ((iLast >> 4) << 8) + idxCC[iRow][iLast & 0xf];
- for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 16; iColumn ++){
- const size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cFullChannel; iChannel ++)
- pCh[iChannel & 15][iPos] = pCh[iChannel & 15][iPosLast];
- }
- }
- if(cfExt == YUV_422) // pad YUV_422 UV
- for(iLast >>= 1, iRow = 0; iRow < 16; iRow ++){
- const size_t iPosLast = ((iLast >> 3) << 7) + idxCC[iRow][iLast & 7];
- for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){
- const size_t iPos = ((iColumn >> 3) << 7) + idxCC[iRow][iColumn & 7];
- for(iChannel = 1; iChannel < 3; iChannel ++)
- pCh[iChannel][iPos] = pCh[iChannel][iPosLast];
- }
- }
- else if(cfExt == YUV_420) // pad YUV_420 UV
- for(iLast >>= 1, iRow = 0; iRow < 8; iRow ++){
- const size_t iPosLast = ((iLast >> 3) << 6) + idxCC_420[iRow][iLast & 7];
- for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){
- const size_t iPos = ((iColumn >> 3) << 6) + idxCC_420[iRow][iColumn & 7];
- for(iChannel = 1; iChannel < 3; iChannel ++)
- pCh[iChannel][iPos] = pCh[iChannel][iPosLast];
- }
- }
- }
- }
- // centralized alpha channel color conversion, small perf penalty
- Int inputMBRowAlpha(CWMImageStrCodec* pSC)
- {
- if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // alpha channel is present
- const size_t cShift = (pSC->m_pNextSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0);
- const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth;
- const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha
- const size_t cRow = pSC->WMIBI.cLine;
- const size_t cColumn = pSC->WMII.cWidth;
- const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv;
- PixelI * pA = pSC->m_pNextSC->p1MBbuffer[0];
- size_t iRow, iColumn;
- for(iRow = 0; iRow < 16; iRow ++){
- if(bdExt == BD_8){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3);
- const U8 * pSrc = pSrc0;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((PixelI)pSrc[iAlphaPos] - (1 << 7)) << cShift;
- }
- else if(bdExt == BD_16){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16);
- const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
- const U16 * pSrc = (U16 *)pSrc0;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((((PixelI)pSrc[iAlphaPos] - (1 << 15)) >> nLenMantissaOrShift) << cShift);
- }
- else if(bdExt == BD_16S){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I16);
- const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
- const I16 * pSrc = (I16 *)pSrc0;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift);
- }
- else if(bdExt == BD_16F){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16);
- const I16 * pSrc = (I16 *)pSrc0;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = forwardHalf (pSrc[iAlphaPos]) << cShift;
- }
- else if(bdExt == BD_32S){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I32);
- const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
- const I32 * pSrc = (I32 *)pSrc0;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift);
- }
- else if(bdExt == BD_32F){
- const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(float);
- const U8 nLen = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
- const I8 nExpBias = pSC->m_pNextSC->WMISCP.nExpBias;
- const float * pSrc = (float *)pSrc0;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = float2pixel (pSrc[iAlphaPos], nExpBias, nLen) << cShift;
- }
- else // not supported
- return ICERR_ERROR;
- if(iRow + 1 < cRow) // vertical padding!
- pSrc0 += pSC->WMIBI.cbStride;
- for(iColumn = cColumn; iColumn < pSC->cmbWidth * 16; iColumn ++) // horizontal padding
- pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = pA[(((cColumn - 1) >> 4) << 8) + idxCC[iRow][(cColumn - 1) & 0xf]];
- }
- }
-
- return ICERR_OK;
- }
- // input one MB row of image data from input buffer
- Int inputMBRow(CWMImageStrCodec* pSC)
- {
- const size_t cShift = (pSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0);
- const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth;
- COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
- const COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
- const size_t cPixelStride = (pSC->WMII.cBitsPerUnit >> 3);
- const size_t iRowStride =
- (cfExt == YUV_420 || (pSC->WMISCP.bYUVData && pSC->m_param.cfColorFormat==YUV_420)) ? 2 : 1;
- const size_t cRow = pSC->WMIBI.cLine;
- const size_t cColumn = pSC->WMII.cWidth;
- const size_t iB = (pSC->WMII.bRGB ? 2 : 0);
- const size_t iR = 2 - iB;
- const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv;
- const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
- const I8 nExpBias = pSC->WMISCP.nExpBias;
- PixelI *pY = pSC->p1MBbuffer[0], *pU = pSC->p1MBbuffer[1], *pV = pSC->p1MBbuffer[2];
- size_t iRow, iColumn, iPos;
- // guard input buffer
- if(checkImageBuffer(pSC, cColumn, cRow) != ICERR_OK)
- return ICERR_ERROR;
- if(pSC->m_bUVResolutionChange) // will do downsampling somewhere else!
- pU = pSC->pResU, pV = pSC->pResV;
- else if(cfInt == Y_ONLY) // xxx to Y_ONLY transcoding!
- pU = pV = pY; // write pY AFTER pU and pV so Y will overwrite U&V
- for(iRow = 0; iRow < 16; iRow += iRowStride){
- if (pSC->WMISCP.bYUVData){
- I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding;
- switch(pSC->m_param.cfColorFormat){
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->m_param.cNumChannels;
- PixelI * pChannel[16];
- size_t iChannel;
- assert(cChannel <= 16);
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
- if(pSC->m_bUVResolutionChange)
- pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cChannel){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pChannel[iChannel & 15][iPos] = (PixelI)pSrc[iChannel & 15];
- }
- }
- break;
- case YUV_422:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 4){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
- pU[iPos] = (PixelI)pSrc[0];
- pV[iPos] = (PixelI)pSrc[2];
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[1];
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[3];
- }
- break;
- case YUV_420:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 6){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
- pU[iPos] = (PixelI)pSrc[4];
- pV[iPos] = (PixelI)pSrc[5];
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[0];
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[1];
- pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (PixelI)pSrc[2];
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (PixelI)pSrc[3];
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_8){
- const U8 * pSrc = pSrc0 + pSC->WMII.cLeadingPadding;
- const PixelI iOffset = (128 << cShift);
- switch(cfExt){
- case CF_RGB:
- assert (pSC->m_bSecondary == FALSE);
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI r = ((PixelI)pSrc[iR]) << cShift, g = ((PixelI)pSrc[1]) << cShift, b = ((PixelI)pSrc[iB]) << cShift;
- _CC(r, g, b); // color conversion
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->m_param.cNumChannels;
- PixelI * pChannel[16];
- size_t iChannel;
- assert(cChannel <= 16);
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
- if(pSC->m_bUVResolutionChange)
- pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pChannel[iChannel & 15][iPos] = (((PixelI)pSrc[iChannel & 15]) << cShift) - iOffset;
- }
- break;
- }
- case CF_RGBE:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI iExp = (PixelI)pSrc[3];
- PixelI r = forwardRGBE (pSrc[0], iExp) << cShift;
- PixelI g = forwardRGBE (pSrc[1], iExp) << cShift;
- PixelI b = forwardRGBE (pSrc[2], iExp) << cShift;
- _CC(r, g, b);
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
- }
- break;
- case CMYK:
- {
- PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI c = ((PixelI)pSrc[0]) << cShift;
- PixelI m = ((PixelI)pSrc[1]) << cShift;
- PixelI y = ((PixelI)pSrc[2]) << cShift;
- PixelI k = ((PixelI)pSrc[3]) << cShift;
- _CC_CMYK(c, m, y, k);
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m;
- }
- break;
- }
- case YUV_422:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
- pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset;
- pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset;
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
- }
- break;
- case YUV_420:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
- pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset;
- pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset;
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
- pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_16){
- const U16 * pSrc = (U16 *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(U16);
- const PixelI iOffset = ((1 << 15) >> nLen) << cShift;
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift;
-
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel;
- size_t iChannel;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift) - iOffset;
- }
- break;
- }
- case CMYK:
- {
- PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift;
- PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift;
- PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift;
- PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift;
- _CC_CMYK(c, m, y, k);
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m;
- }
- break;
- }
- case YUV_422:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
- pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset;
- pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset;
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
- }
- break;
- case YUV_420:
- for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){
- if(cfInt != Y_ONLY){
- iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
- pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset;
- pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset;
- }
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
- pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset;
- pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_16S){
- const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(I16);
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift;
-
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel;
- size_t iChannel;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift);
- }
- }
- break;
- case CMYK:
- {
- PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift;
- PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift;
- PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift;
- PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift;
-
- _CC_CMYK(c, m, y, k);
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = -m;
- }
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_16F){
- const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(U16);
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = forwardHalf (pSrc[0]) << cShift;
- PixelI g = forwardHalf (pSrc[1]) << cShift;
- PixelI b = forwardHalf (pSrc[2]) << cShift;
-
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding!
- size_t iChannel;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = forwardHalf (pSrc[iChannel]) << cShift;
- }
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_32){
- const U32 * pSrc = (U32 *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(U32);
- const PixelI iOffset = ((1 << 31) >> nLen) << cShift;
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = (pSrc[0] >> nLen) << cShift, g = (pSrc[1] >> nLen) << cShift, b = (pSrc[2] >> nLen) << cShift;
-
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel;
- size_t iChannel;
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift;
- }
- break;
- }
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_32S){
- const I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(I32);
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = (pSrc[0] >> nLen)<< cShift, g = (pSrc[1] >> nLen)<< cShift, b = (pSrc[2] >> nLen)<< cShift;
-
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding!
- size_t iChannel;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift;
- }
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_32F){
- const float * pSrc = (float *)pSrc0 + pSC->WMII.cLeadingPadding;
- const size_t cStride = cPixelStride / sizeof(float);
- switch(cfExt){
- case CF_RGB:
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- PixelI r = float2pixel (pSrc[0], nExpBias, nLen) << cShift;
- PixelI g = float2pixel (pSrc[1], nExpBias, nLen) << cShift;
- PixelI b = float2pixel (pSrc[2], nExpBias, nLen) << cShift;
- _CC(r, g, b); // color conversion
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
- }
- break;
- case Y_ONLY:
- case YUV_444:
- case NCOMPONENT:
- {
- const size_t cChannel = pSC->WMISCP.cChannel;
- size_t iChannel;
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- for(iChannel = 0; iChannel < cChannel; iChannel ++)
- pSC->p1MBbuffer[iChannel][iPos] = float2pixel (pSrc[iChannel], nExpBias, nLen) << cShift;
- }
- }
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(bdExt == BD_5){ // RGB 555, work for both big endian and small endian!
- const U8 * pSrc = pSrc0;
- const PixelI iOffset = (16 << cShift);
- assert(cfExt == CF_RGB);
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = ((g >> 2) & 0x1F) << cShift;
- g = ((r >> 5) + ((g & 3) << 3)) << cShift, r = (r & 0x1F) << cShift;
- _CC(r, g, b); // color conversion
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- }
- else if(bdExt == BD_565){ // RGB 555, work for both big endian and small endian!
- const U8 * pSrc = pSrc0;
- const PixelI iOffset = (32 << cShift);
- assert(cfExt == CF_RGB);
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (g >> 3) << (cShift + 1);
- g = ((r >> 5) + ((g & 7) << 3)) << cShift, r = (r & 0x1F) << (cShift + 1);
- _CC(r, g, b); // color conversion
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- }
- else if(bdExt == BD_10){ //RGB 101010, work for both big endian and small endian!
- const U8 * pSrc = pSrc0;
- const PixelI iOffset = (512 << cShift);
- assert(cfExt == CF_RGB);
-
- for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
- PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (PixelI)pSrc[2];
- r = (r + ((g & 3) << 8)) << cShift, g = ((g >> 2) + ((b & 0xF) << 6)) << cShift;
- b = ((b >> 4) + (((PixelI)pSrc[3] & 0x3F) << 4)) << cShift;
- _CC(r, g, b); // color conversion
-
- iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
- pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
- }
- }
- else if(bdExt == BD_1){
- assert(cfExt == Y_ONLY);
- for(iColumn = 0; iColumn < cColumn; iColumn ++) {
- pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((pSC->WMISCP.bBlackWhite + (pSrc0[iColumn >> 3] >> (7 - (iColumn & 7)))) & 1) << cShift;
- }
- }
- if(iRow + iRowStride < cRow) // centralized vertical padding!
- pSrc0 += pSC->WMIBI.cbStride;
- }
- padHorizontally(pSC); // centralized horizontal padding
- // centralized down-sampling
- if(pSC->m_bUVResolutionChange)
- downsampleUV(pSC);
- // centralized alpha channel handdling
- if (pSC->WMISCP.uAlphaMode == 3)
- if(inputMBRowAlpha(pSC) != ICERR_OK)
- return ICERR_ERROR;
- return ICERR_OK;
- }
|