1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252 |
- //*@@@+++@@@@******************************************************************
- //
- // 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 "perfTimer.h"
- #ifdef MEM_TRACE
- #define TRACE_MALLOC 1
- #define TRACE_NEW 0
- #define TRACE_HEAP 0
- #include "memtrace.h"
- #endif
- //================================================================
- // Quantization index tables
- //================================================================
- const int blkOffset[16] = {0, 64, 16, 80, 128, 192, 144, 208, 32, 96, 48, 112, 160, 224, 176, 240};
- const int blkOffsetUV[4] = {0, 32, 16, 48};
- const int blkOffsetUV_422[8] = {0, 64, 16, 80, 32, 96, 48, 112};
- const int dctIndex[3][16] = { /** permutation matrix tailored to the transform, nothing to do with ZZS **/
- {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 444
- {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 420
- {0,128,64,208, 32,240,48,224, 16,192,80,144, 112,176,96,160 }, //DC 444
- };
- //================================================================
- // Color conversion index table
- //================================================================
- const U8 idxCC[16][16] =
- {
- {0x00, 0x01, 0x05, 0x04, 0x40, 0x41, 0x45, 0x44, 0x80, 0x81, 0x85, 0x84, 0xc0, 0xc1, 0xc5, 0xc4, },
- {0x02, 0x03, 0x07, 0x06, 0x42, 0x43, 0x47, 0x46, 0x82, 0x83, 0x87, 0x86, 0xc2, 0xc3, 0xc7, 0xc6, },
- {0x0a, 0x0b, 0x0f, 0x0e, 0x4a, 0x4b, 0x4f, 0x4e, 0x8a, 0x8b, 0x8f, 0x8e, 0xca, 0xcb, 0xcf, 0xce, },
- {0x08, 0x09, 0x0d, 0x0c, 0x48, 0x49, 0x4d, 0x4c, 0x88, 0x89, 0x8d, 0x8c, 0xc8, 0xc9, 0xcd, 0xcc, },
- {0x10, 0x11, 0x15, 0x14, 0x50, 0x51, 0x55, 0x54, 0x90, 0x91, 0x95, 0x94, 0xd0, 0xd1, 0xd5, 0xd4, },
- {0x12, 0x13, 0x17, 0x16, 0x52, 0x53, 0x57, 0x56, 0x92, 0x93, 0x97, 0x96, 0xd2, 0xd3, 0xd7, 0xd6, },
- {0x1a, 0x1b, 0x1f, 0x1e, 0x5a, 0x5b, 0x5f, 0x5e, 0x9a, 0x9b, 0x9f, 0x9e, 0xda, 0xdb, 0xdf, 0xde, },
- {0x18, 0x19, 0x1d, 0x1c, 0x58, 0x59, 0x5d, 0x5c, 0x98, 0x99, 0x9d, 0x9c, 0xd8, 0xd9, 0xdd, 0xdc, },
- {0x20, 0x21, 0x25, 0x24, 0x60, 0x61, 0x65, 0x64, 0xa0, 0xa1, 0xa5, 0xa4, 0xe0, 0xe1, 0xe5, 0xe4, },
- {0x22, 0x23, 0x27, 0x26, 0x62, 0x63, 0x67, 0x66, 0xa2, 0xa3, 0xa7, 0xa6, 0xe2, 0xe3, 0xe7, 0xe6, },
- {0x2a, 0x2b, 0x2f, 0x2e, 0x6a, 0x6b, 0x6f, 0x6e, 0xaa, 0xab, 0xaf, 0xae, 0xea, 0xeb, 0xef, 0xee, },
- {0x28, 0x29, 0x2d, 0x2c, 0x68, 0x69, 0x6d, 0x6c, 0xa8, 0xa9, 0xad, 0xac, 0xe8, 0xe9, 0xed, 0xec, },
- {0x30, 0x31, 0x35, 0x34, 0x70, 0x71, 0x75, 0x74, 0xb0, 0xb1, 0xb5, 0xb4, 0xf0, 0xf1, 0xf5, 0xf4, },
- {0x32, 0x33, 0x37, 0x36, 0x72, 0x73, 0x77, 0x76, 0xb2, 0xb3, 0xb7, 0xb6, 0xf2, 0xf3, 0xf7, 0xf6, },
- {0x3a, 0x3b, 0x3f, 0x3e, 0x7a, 0x7b, 0x7f, 0x7e, 0xba, 0xbb, 0xbf, 0xbe, 0xfa, 0xfb, 0xff, 0xfe, },
- {0x38, 0x39, 0x3d, 0x3c, 0x78, 0x79, 0x7d, 0x7c, 0xb8, 0xb9, 0xbd, 0xbc, 0xf8, 0xf9, 0xfd, 0xfc, },
- };
- const U8 idxCC_420[8][8] =
- {
- {0x00, 0x01, 0x05, 0x04, 0x20, 0x21, 0x25, 0x24, },
- {0x02, 0x03, 0x07, 0x06, 0x22, 0x23, 0x27, 0x26, },
- {0x0a, 0x0b, 0x0f, 0x0e, 0x2a, 0x2b, 0x2f, 0x2e, },
- {0x08, 0x09, 0x0d, 0x0c, 0x28, 0x29, 0x2d, 0x2c, },
- {0x10, 0x11, 0x15, 0x14, 0x30, 0x31, 0x35, 0x34, },
- {0x12, 0x13, 0x17, 0x16, 0x32, 0x33, 0x37, 0x36, },
- {0x1a, 0x1b, 0x1f, 0x1e, 0x3a, 0x3b, 0x3f, 0x3e, },
- {0x18, 0x19, 0x1d, 0x1c, 0x38, 0x39, 0x3d, 0x3c, },
- };
- /*************************************************************************
- gGDISignature
- *************************************************************************/
- const Char gGDISignature[] = {'W', 'M', 'P', 'H', 'O', 'T', 'O', '\0'};
- // check if enough memory allocated for the image buffer
- Int checkImageBuffer(CWMImageStrCodec * pSC, size_t cWidth, size_t cRows)
- {
- const BITDEPTH_BITS bd = pSC->WMISCP.bYUVData ?
- BD_32S : pSC->WMII.bdBitDepth;
- const COLORFORMAT cf = pSC->WMISCP.bYUVData ?
- pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat;
- size_t cBytes;
- Bool bLessThan64Bit = sizeof(void *) < 8;
- if(cf == YUV_420)
- cRows = (cRows + 1) / 2;
- if(cRows > pSC->WMIBI.cLine)
- return ICERR_ERROR;
- if(cf == YUV_422 || cf == YUV_420)
- cWidth = (cWidth + 1) / 2;
- if (bLessThan64Bit && (cWidth >> ((sizeof(size_t) * 8 - 5)))) {
- /** potential overflow - 32 bit pointers insufficient to address cache **/
- /** this uses 2 macroblock row constraint, which is tighter than ensuring rollover doesn't occur below **/
- return ICERR_ERROR;
- }
- cBytes = pSC->WMISCP.bYUVData ? cWidth * sizeof(PixelI) *
- (cf == YUV_420 ? 6 : (cf == YUV_422 ? 4 : (cf == YUV_444 ? 3 : 1))) :
- (bd == BD_1 ? (pSC->WMII.cBitsPerUnit * cWidth + 7) / 8 : (pSC->WMII.cBitsPerUnit + 7) / 8 * cWidth);
- return (cBytes > pSC->WMIBI.cbStride ? ICERR_ERROR : ICERR_OK);
- }
- Void writeQPIndex(BitIOInfo * pIO, U8 uiIndex, U32 cBits)
- {
- if(uiIndex == 0)
- putBit16(pIO, 1, 1); // default QP
- else{
- putBit16(pIO, 0, 1); // non default QP
- putBit16(pIO, uiIndex - 1, cBits);
- }
- }
- U8 readQPIndex(BitIOInfo * pIO, U32 cBits)
- {
- if(getBit16(pIO, 1))
- return 0; // default QP
- return (U8) getBit16(pIO, cBits) + 1;
- }
- Void getTilePos(CWMImageStrCodec* pSC, size_t mbX, size_t mbY)
- {
- if(mbX == 0){ // left image boundary
- pSC->cTileColumn = 0;
- }
- else if(pSC->cTileColumn < pSC->WMISCP.cNumOfSliceMinus1V && mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1]){ // left tile boundary
- pSC->cTileColumn ++;
- }
- if(mbY == 0){ // top image boundary
- pSC->cTileRow = 0;
- }
- else if(pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && mbY == pSC->WMISCP.uiTileY[pSC->cTileRow + 1]){ // top tile boundary
- pSC->cTileRow ++;
- }
- pSC->m_bCtxLeft = (mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn]);
- pSC->m_bCtxTop = (mbY == pSC->WMISCP.uiTileY[pSC->cTileRow]);
- pSC->m_bResetContext = pSC->m_bResetRGITotals = (((mbX - pSC->WMISCP.uiTileX[pSC->cTileColumn]) & 0xf) == 0);
- if(pSC->cTileColumn == pSC->WMISCP.cNumOfSliceMinus1V){ // last tile column
- if(mbX + 1 == pSC->cmbWidth)
- pSC->m_bResetContext = TRUE;
- }
- else if(mbX + 1 == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1])
- pSC->m_bResetContext = TRUE;
- }
- //================================================================
- // utility functions for 2 macro block rows
- //================================================================
- Void initMRPtr(CWMImageStrCodec* pSC)
- {
- size_t j, jend = (pSC->m_pNextSC != NULL);
- for (j = 0; j <= jend; j++) {
- memcpy (pSC->p0MBbuffer, pSC->a0MBbuffer, sizeof (pSC->p0MBbuffer));
- memcpy (pSC->p1MBbuffer, pSC->a1MBbuffer, sizeof (pSC->p1MBbuffer));
- pSC = pSC->m_pNextSC;
- }
- }
- Void advanceMRPtr(CWMImageStrCodec* pSC)
- {
- const COLORFORMAT cf = pSC->m_param.cfColorFormat;
- const int cpChroma = cblkChromas[cf] * 16;
- size_t i, j, jend = (pSC->m_pNextSC != NULL);
- assert(pSC->m_bSecondary == FALSE);
- for (j = 0; j <= jend; j++) {
- int cpStride = 16 * 16;
- for (i = 0; i < pSC->m_param.cNumChannels; i++) {
- pSC->pPlane[i] = pSC->p0MBbuffer[i];
- pSC->p0MBbuffer[i] += cpStride;
- pSC->p1MBbuffer[i] += cpStride;
- cpStride = cpChroma;
- }
- pSC = pSC->m_pNextSC;
- }
- }
- /* advance to next MB row */
- Void advanceOneMBRow(CWMImageStrCodec *pSC)
- {
- size_t i, j, jend = (pSC->m_pNextSC != NULL);
- CWMIPredInfo *pPredInfo;
- for (j = 0; j <= jend; j++) {
- for(i = 0; i < pSC->m_param.cNumChannels; i ++){ // swap current row and previous row
- pPredInfo = pSC->PredInfo[i];
- pSC->PredInfo[i] = pSC->PredInfoPrevRow[i];
- pSC->PredInfoPrevRow[i] = pPredInfo;
- }
- pSC = pSC->m_pNextSC;
- }
- }
- Void swapMRPtr(CWMImageStrCodec* pSC)
- {
- PixelI *pTemp[MAX_CHANNELS];
- size_t j, jend = (pSC->m_pNextSC != NULL);
- for (j = 0; j <= jend; j++) {
- memcpy (pTemp, pSC->a0MBbuffer, sizeof (pSC->a0MBbuffer));
- memcpy (pSC->a0MBbuffer, pSC->a1MBbuffer, sizeof (pSC->a0MBbuffer));
- memcpy (pSC->a1MBbuffer, pTemp, sizeof (pSC->a0MBbuffer));
- pSC = pSC->m_pNextSC;
- }
- }
- //================================================================
- // Empty function to fill slot
- //================================================================
- Int IDPEmpty(CWMImageStrCodec* pSC)
- {
- UNREFERENCED_PARAMETER( pSC );
- return ICERR_OK;
- }
- ERR WMPAlloc(void** ppv, size_t cb)
- {
- *ppv = calloc(1, cb);
- return *ppv ? WMP_errSuccess : WMP_errOutOfMemory;
- }
- ERR WMPFree(void** ppv)
- {
- if (*ppv)
- {
- free(*ppv);
- *ppv = NULL;
- }
- return WMP_errSuccess;
- }
- //================================================================
- // Streaming I/O functions
- //================================================================
- ERR CreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode)
- {
- ERR err = WMP_errSuccess;
- struct WMPStream* pWS = NULL;
- Call(WMPAlloc((void** )ppWS, sizeof(**ppWS)));
- pWS = *ppWS;
- pWS->Close = CloseWS_File;
- pWS->EOS = EOSWS_File;
- pWS->Read = ReadWS_File;
- pWS->Write = WriteWS_File;
- //pWS->GetLine = GetLineWS_File;
- pWS->SetPos = SetPosWS_File;
- pWS->GetPos = GetPosWS_File;
- #ifdef WIN32
- FailIf(0 != fopen_s(&pWS->state.file.pFile, szFilename, szMode), WMP_errFileIO);
- #else
- pWS->state.file.pFile = fopen(szFilename, szMode);
- FailIf(NULL == pWS->state.file.pFile, WMP_errFileIO);
- #endif
- Cleanup:
- return err;
- }
- ERR CloseWS_File(struct WMPStream** ppWS)
- {
- ERR err = WMP_errSuccess;
- struct WMPStream* pWS = *ppWS;
- fclose(pWS->state.file.pFile);
- Call(WMPFree((void**)ppWS));
- Cleanup:
- return err;
- }
- Bool EOSWS_File(struct WMPStream* pWS)
- {
- return feof(pWS->state.file.pFile);
- }
- ERR ReadWS_File(struct WMPStream* pWS, void* pv, size_t cb)
- {
- // ERR err = WMP_errSuccess;
- return (fread(pv, cb, 1, pWS->state.file.pFile) == 1) ? WMP_errSuccess : WMP_errFileIO;
- }
- ERR WriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- if(0 != cb)
- {
- FailIf(1 != fwrite(pv, cb, 1, pWS->state.file.pFile), WMP_errFileIO);
- }
- Cleanup:
- return err;
- }
- ERR SetPosWS_File(struct WMPStream* pWS, size_t offPos)
- {
- ERR err = WMP_errSuccess;
- FailIf(0 != fseek(pWS->state.file.pFile, (long)offPos, SEEK_SET), WMP_errFileIO);
- Cleanup:
- return err;
- }
- ERR GetPosWS_File(struct WMPStream* pWS, size_t* poffPos)
- {
- ERR err = WMP_errSuccess;
- long lOff = 0;
- FailIf(-1 == (lOff = ftell(pWS->state.file.pFile)), WMP_errFileIO);
- *poffPos = (size_t)lOff;
- Cleanup:
- return err;
- }
- //----------------------------------------------------------------
- ERR CreateWS_Memory(struct WMPStream** ppWS, void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- struct WMPStream* pWS = NULL;
- Call(WMPAlloc((void** )ppWS, sizeof(**ppWS)));
- pWS = *ppWS;
- pWS->state.buf.pbBuf = pv;
- pWS->state.buf.cbBuf = cb;
- pWS->state.buf.cbCur = 0;
- pWS->Close = CloseWS_Memory;
- pWS->EOS = EOSWS_Memory;
- pWS->Read = ReadWS_Memory;
- pWS->Write = WriteWS_Memory;
- pWS->SetPos = SetPosWS_Memory;
- pWS->GetPos = GetPosWS_Memory;
- Cleanup:
- return err;
- }
- ERR CloseWS_Memory(struct WMPStream** ppWS)
- {
- ERR err = WMP_errSuccess;
- Call(WMPFree((void**)ppWS));
-
- Cleanup:
- return err;
- }
- Bool EOSWS_Memory(struct WMPStream* pWS)
- {
- return pWS->state.buf.cbBuf <= pWS->state.buf.cbCur;
- }
- ERR ReadWS_Memory(struct WMPStream* pWS, void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- // FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur, WMP_errBufferOverflow);
- if(pWS->state.buf.cbBuf < pWS->state.buf.cbCur)
- return err;
- FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
- if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb)
- {
- cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur;
- }
- memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cb);
- pWS->state.buf.cbCur += cb;
- Cleanup:
- return err;
- }
- ERR WriteWS_Memory(struct WMPStream* pWS, const void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
- FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow);
- memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cb);
- pWS->state.buf.cbCur += cb;
- Cleanup:
- return err;
- }
- ERR SetPosWS_Memory(struct WMPStream* pWS, size_t offPos)
- {
- ERR err = WMP_errSuccess;
- //While the following condition is possibly useful, failure occurs
- //at the end of a file since packets beyond the end may be accessed
- //FailIf(pWS->state.buf.cbBuf < offPos, WMP_errBufferOverflow);
- pWS->state.buf.cbCur = offPos;
- //Cleanup:
- return err;
- }
- ERR GetPosWS_Memory(struct WMPStream* pWS, size_t* poffPos)
- {
- *poffPos = pWS->state.buf.cbCur;
- return WMP_errSuccess;
- }
- //=================================================================
- // Linked list based WMPStream
- // - for indefinite size, multiple stream out
- // - reads not supported in this mode
- //=================================================================
- ERR CreateWS_List(struct WMPStream** ppWS)
- {
- ERR err = WMP_errSuccess;
- struct WMPStream* pWS = NULL;
- Call(WMPAlloc((void** )ppWS, sizeof(**ppWS) + PACKETLENGTH + sizeof(void *)));
- pWS = *ppWS;
- pWS->state.buf.pbBuf = (U8 *)pWS + sizeof(**ppWS) + sizeof(void *); // first buffer points here
- memset(pWS->state.buf.pbBuf - sizeof(void *), 0, sizeof(void *));
- pWS->state.buf.cbBuf = PACKETLENGTH;
- pWS->state.buf.cbCur = 0;
- pWS->state.buf.cbBufCount = 0;
- pWS->Close = CloseWS_List;
- pWS->EOS = NULL; // doesn't get called
- pWS->Read = ReadWS_List;
- pWS->Write = WriteWS_List;
- pWS->SetPos = SetPosWS_List;
- pWS->GetPos = GetPosWS_List;
- //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
- Cleanup:
- return err;
- }
- ERR CloseWS_List(struct WMPStream** ppWS)
- {
- ERR err = WMP_errSuccess;
- if (ppWS) {
- U8 *pBuf = (U8 *)(ppWS[0] + 1); // pointer to buffer
- U8 *pNext = (U8 *)(((void **)pBuf)[0]);
- while (pNext) {
- //struct WMPStream *pWS = ppWS[0];
- pBuf = pNext;
- pNext = (U8 *)(((void **)(pBuf))[0]);
- //printf ("delete buffer %x\n", pBuf);
- Call(WMPFree((void**)&pBuf));
- }
- }
- Call(WMPFree((void**)ppWS));
-
- Cleanup:
- return err;
- }
- ERR ReadWS_List(struct WMPStream* pWS, void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
- if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount + cb)
- {
- cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur - PACKETLENGTH * pWS->state.buf.cbBufCount;
- }
- while (cb) {
- size_t cl = PACKETLENGTH - pWS->state.buf.cbCur;
- if (cl > cb)
- cl = cb;
- memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cl);
- pWS->state.buf.cbCur += cl;
- pv = (void *)((U8 *)pv + cl);
- cb -= cl;
- if (pWS->state.buf.cbCur == PACKETLENGTH) {
- pWS->state.buf.pbBuf = (U8 *)((void **)(pWS->state.buf.pbBuf - sizeof(void *)))[0] + sizeof(void *);
- pWS->state.buf.cbCur = 0;
- pWS->state.buf.cbBufCount++;
- //printf ("read buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
- }
- }
- Cleanup:
- return err;
- }
- ERR WriteWS_List(struct WMPStream* pWS, const void* pv, size_t cb)
- {
- ERR err = WMP_errSuccess;
- FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
- FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow);
- while (cb) {
- size_t cl = PACKETLENGTH - pWS->state.buf.cbCur;
- if (cl > cb)
- cl = cb;
- memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cl);
- pWS->state.buf.cbCur += cl;
- pv = (const void *)((U8 *)pv + cl);
- cb -= cl;
- if (pWS->state.buf.cbCur == PACKETLENGTH) { // allocate next packet in list
- U8 *pBuf = NULL;
- void **pPtrLoc = (void **)(pWS->state.buf.pbBuf - sizeof(void *));
- Call(WMPAlloc((void **)&pBuf, PACKETLENGTH + sizeof(void *)));
- pPtrLoc[0] = (void *)pBuf;
- pWS->state.buf.pbBuf = pBuf + sizeof(void *);
- pWS->state.buf.cbBuf += PACKETLENGTH;
- memset(pBuf, 0, sizeof(void *));
- pWS->state.buf.cbCur = 0;
- pWS->state.buf.cbBufCount++;
- //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
- }
- }
- Cleanup:
- return err;
- }
- ERR SetPosWS_List(struct WMPStream* pWS, size_t offPos)
- {
- ERR err = WMP_errSuccess;
- // get the first buffer
- U8 *pBuf = (U8 *)(pWS + 1); // pointer to buffer
- pWS->state.buf.cbCur = 0;
- pWS->state.buf.cbBufCount = 0;
- while (offPos >= PACKETLENGTH && pBuf != NULL) {
- pBuf = (U8 *)(((void **)pBuf)[0]);
- offPos -= PACKETLENGTH;
- pWS->state.buf.cbBufCount++;
- }
- if (pBuf == NULL)
- goto Cleanup;
- pWS->state.buf.cbCur = offPos;
- pWS->state.buf.pbBuf = pBuf + sizeof(void *);
- //printf ("seek buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
- Cleanup:
- return err;
- }
- ERR GetPosWS_List(struct WMPStream* pWS, size_t* poffPos)
- {
- *poffPos = pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount;
- return WMP_errSuccess;
- }
- //================================================================
- // Simple BitIO access functions
- //================================================================
- // init SimpleBitIO
- ERR attach_SB(SimpleBitIO* pSB, struct WMPStream* pWS)
- {
- pSB->pWS = pWS;
- pSB->cbRead = 0;
- pSB->bAccumulator = 0;
- pSB->cBitLeft = 0;
- return WMP_errSuccess;
- }
- // extract upto 32bit from input stream
- U32 getBit32_SB(SimpleBitIO* pSB, U32 cBits)
- {
- U32 rc = 0;
- while (pSB->cBitLeft < cBits)
- {
- rc <<= pSB->cBitLeft;
- rc |= pSB->bAccumulator >> (8 - pSB->cBitLeft);
- cBits -= pSB->cBitLeft;
- pSB->pWS->Read(pSB->pWS, &pSB->bAccumulator, 1);
- pSB->cbRead++;
- pSB->cBitLeft = 8;
- }
- rc <<= cBits;
- rc |= pSB->bAccumulator >> (8 - cBits);
- pSB->bAccumulator <<= cBits;
- pSB->cBitLeft -= cBits;
- return rc;
- }
- // ignore input to byte boundary
- Void flushToByte_SB(SimpleBitIO* pSB)
- {
- pSB->bAccumulator = 0;
- pSB->cBitLeft = 0;
- }
- // return read byte count
- U32 getByteRead_SB(SimpleBitIO* pSB)
- {
- return pSB->cbRead;
- }
- ERR detach_SB(SimpleBitIO* pSB)
- {
- assert(0 == pSB->cBitLeft);
- pSB->pWS = NULL;
- return WMP_errSuccess;
- }
- //================================================================
- // Memory access functions
- //================================================================
- #if (defined(WIN32) && !defined(UNDER_CE)) || (defined(UNDER_CE) && defined(_ARM_))
- // WinCE ARM and Desktop x86
- #else
- // other platform
- #ifdef _BIG__ENDIAN_
- #define _byteswap_ulong(x) (x)
- #else // _BIG__ENDIAN_
- U32 _byteswap_ulong(U32 bits)
- {
- U32 r = (bits & 0xffu) << 24;
- r |= (bits << 8) & 0xff0000u;
- r |= ((bits >> 8) & 0xff00u);
- r |= ((bits >> 24) & 0xffu);
- return r;
- }
- #endif // _BIG__ENDIAN_
- #endif
- U32 load4BE(void* pv)
- {
- #ifdef _BIG__ENDIAN_
- return (*(U32*)pv);
- #else // _BIG__ENDIAN_
- #if defined(_M_IA64) || defined(_ARM_)
- U32 v;
- v = ((U16 *) pv)[0];
- v |= ((U32)((U16 *) pv)[1]) << 16;
- return _byteswap_ulong(v);
- #else // _M_IA64
- return _byteswap_ulong(*(U32*)pv);
- #endif // _M_IA64
- #endif // _BIG__ENDIAN_
- }
- #define LOAD16 load4BE
- #ifdef _BIG__ENDIAN_
- #define WRITESWAP_ENDIAN(a) ((a)>>16)
- #else // _BIG__ENDIAN_
- #define WRITESWAP_ENDIAN(a) _byteswap_ulong(a)
- #endif // _BIG__ENDIAN_
- //================================================================
- // Bit I/O functions
- //================================================================
- Int allocateBitIOInfo(CWMImageStrCodec* pSC)
- {
- U32 cNumBitIO;
- SUBBAND sbSubband = pSC->WMISCP.sbSubband;
- pSC->cSB = (sbSubband == SB_DC_ONLY ? 1 : (sbSubband == SB_NO_HIGHPASS ? 2 : (sbSubband == SB_NO_FLEXBITS ? 3 : 4)));
- // # of additional BitIOs other than pSC->pIOHeader
- if (!pSC->m_param.bIndexTable) { // pure streaming mode, no index table, no additional BitIO!
- assert (pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0);
- cNumBitIO = 0;
- }
- else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL)
- cNumBitIO = pSC->WMISCP.cNumOfSliceMinus1V + 1;
- else
- cNumBitIO = (pSC->WMISCP.cNumOfSliceMinus1V + 1) * pSC->cSB;
- if(cNumBitIO > MAX_TILES * 4)
- return ICERR_ERROR;
- // allocate additional BitIos
- if(cNumBitIO > 0){
- U32 i = 0;
- size_t cb = sizeof(BitIOInfo) * cNumBitIO + (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 * cNumBitIO;
- U8* pb = (U8*)malloc(cb);
- if (NULL == pb) return ICERR_ERROR;
- memset(pb, 0, cb);
- pSC->m_ppBitIO = (BitIOInfo**)pb;
- pb += sizeof(BitIOInfo) * cNumBitIO;
- pb = (U8*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
- for (i = 0; i < cNumBitIO; ++i){
- pSC->m_ppBitIO[i] = (BitIOInfo*)pb;
- pb += PACKETLENGTH * 4;
- }
- // allocate index table
- if(cNumBitIO > MAX_TILES * 4 || pSC->WMISCP.cNumOfSliceMinus1H >= MAX_TILES)
- return ICERR_ERROR;
- pSC->pIndexTable = malloc(cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1) * sizeof(size_t));
- if(NULL == pSC->pIndexTable) return ICERR_ERROR;
- }
- pSC->cNumBitIO = cNumBitIO;
- return ICERR_OK;
- }
- Int setBitIOPointers(CWMImageStrCodec* pSC)
- {
- if(pSC->cNumBitIO > 0){
- U32 i;
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
- CCodingContext * pContext = &pSC->m_pCodingContext[i];
- if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
- pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->m_ppBitIO[i];
- }
- else{
- U32 j = pSC->cSB;
- pContext->m_pIODC = pSC->m_ppBitIO[i * j];
- if(j > 1)
- pContext->m_pIOLP = pSC->m_ppBitIO[i * j + 1];
- if(j > 2)
- pContext->m_pIOAC = pSC->m_ppBitIO[i * j + 2];
- if(j > 3)
- pContext->m_pIOFL = pSC->m_ppBitIO[i * j + 3];
- }
- }
- }
- else{ // streamimg mode
- CCodingContext * pContext = &pSC->m_pCodingContext[0];
- pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->pIOHeader;
- }
- return ICERR_OK;
- }
- Int allocateTileInfo(CWMImageStrCodec * pSC)
- {
- size_t i;
- if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES)
- return ICERR_ERROR;
- pSC->pTile = (CWMITile *)malloc((pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile));
- if(pSC->pTile == NULL)
- return ICERR_ERROR;
- memset(pSC->pTile, 0, (pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile));
- for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++)
- pSC->pTile[i].cNumQPHP = pSC->pTile[i].cNumQPLP = 1, pSC->pTile[i].cBitsHP = pSC->pTile[i].cBitsLP = 0;
- return ICERR_OK;
- }
- Void freeTileInfo(CWMImageStrCodec * pSC)
- {
- size_t iTile;
- if((pSC->m_param.uQPMode & 1) != 0) // not DC uniform
- for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
- freeQuantizer(pSC->pTile[iTile].pQuantizerDC);
- else
- freeQuantizer(pSC->pTile[0].pQuantizerDC);
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY)
- if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform
- for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
- freeQuantizer(pSC->pTile[iTile].pQuantizerLP);
- else
- freeQuantizer(pSC->pTile[0].pQuantizerLP);
- if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
- if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform
- for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
- freeQuantizer(pSC->pTile[iTile].pQuantizerHP);
- else
- freeQuantizer(pSC->pTile[0].pQuantizerHP);
- if(pSC->pTile != NULL)
- free(pSC->pTile);
- }
- Int allocateQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], size_t cChannel, size_t cQP)
- {
- size_t iCh;
-
- if(cQP > 16 || cChannel > MAX_CHANNELS)
- return ICERR_ERROR;
- pQuantizer[0] = (CWMIQuantizer *)malloc(cQP * sizeof(CWMIQuantizer) * cChannel);
- if(pQuantizer[0] == NULL)
- return ICERR_ERROR;
- for(iCh = 1; iCh < cChannel; iCh ++)
- pQuantizer[iCh] = pQuantizer[iCh - 1] + cQP;
- return ICERR_OK;
- }
- Void freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS])
- {
- if(pQuantizer[0] != NULL)
- free(pQuantizer[0]);
- }
- Void formatQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], U8 cChMode, size_t cCh, size_t iPos, Bool bShiftedUV,
- Bool bScaledArith)
- {
- size_t iCh;
-
- for(iCh = 0; iCh < cCh; iCh ++){
- if(iCh > 0)
- if(cChMode == 0) // uniform
- pQuantizer[iCh][iPos] = pQuantizer[0][iPos];
- else if(cChMode == 1) // mixed
- pQuantizer[iCh][iPos] = pQuantizer[1][iPos];
- remapQP(pQuantizer[iCh] + iPos, (iCh > 0 && bShiftedUV == TRUE) ? SHIFTZERO - 1 : SHIFTZERO, bScaledArith);
- }
- }
- Void setUniformQuantizer(CWMImageStrCodec * pSC, size_t sb)
- {
- size_t iCh, iTile;
- for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
- for(iTile = 1; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
- if(sb == 0) // DC
- pSC->pTile[iTile].pQuantizerDC[iCh] = pSC->pTile[0].pQuantizerDC[iCh];
- else if(sb == 1) // LP
- pSC->pTile[iTile].pQuantizerLP[iCh] = pSC->pTile[0].pQuantizerLP[iCh];
- else // HP
- pSC->pTile[iTile].pQuantizerHP[iCh] = pSC->pTile[0].pQuantizerHP[iCh];
- }
- Void useDCQuantizer(CWMImageStrCodec * pSC, size_t iTile)
- {
- size_t iCh;
- for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
- pSC->pTile[iTile].pQuantizerLP[iCh][0] = *pSC->pTile[iTile].pQuantizerDC[iCh];
- }
- Void useLPQuantizer(CWMImageStrCodec * pSC, size_t cQP, size_t iTile)
- {
- size_t iCh, iQP;
- for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
- for(iQP = 0; iQP < cQP; iQP ++)
- pSC->pTile[iTile].pQuantizerHP[iCh][iQP] = pSC->pTile[iTile].pQuantizerLP[iCh][iQP];
- }
- U8 dquantBits(U8 cQP)
- {
- return (cQP < 2 ? 0 : (cQP < 4 ? 1 : (cQP < 6 ? 2 : (cQP < 10 ? 3 : 4))));
- }
- #ifndef ARMOPT_BITIO
- U32 peekBit16(BitIOInfo* pIO, U32 cBits)
- {
- PEEKBIT16(pIO, cBits);
- }
- U32 flushBit16(BitIOInfo* pIO, U32 cBits)
- {
- FLUSHBIT16(pIO, cBits);
- }
- U32 getBit16(BitIOInfo* pIO, U32 cBits)
- {
- U32 uiRet = peekBit16(pIO, cBits);
- flushBit16(pIO, cBits);
- return uiRet;
- }
- U32 getBool16(BitIOInfo* pIO)
- {
- U32 uiRet = peekBit16(pIO, 1);
- flushBit16(pIO, 1);
- return uiRet;
- }
- /** this function returns cBits if zero is read, or a signed value if first cBits are not all zero **/
- I32 getBit16s(BitIOInfo* pIO, U32 cBits)
- {
- U32 uiRet = peekBit16(pIO, cBits + 1);
- if (uiRet < 2) {
- flushBit16(pIO, cBits);
- return 0;
- }
- else {
- flushBit16(pIO, cBits + 1);
- if (uiRet & 1)
- return (-(I32)(uiRet >> 1));
- else
- return (I32)(uiRet >> 1);
- }
- }
- U32 getBit32(BitIOInfo* pIO, U32 cBits)
- {
- U32 uiRet = 0;
- assert(0 <= (I32)cBits && cBits <= 32);
- if (16 < cBits)
- {
- uiRet = getBit16(pIO, 16);
- cBits -= 16;
- uiRet <<= cBits;
- }
- uiRet |= getBit16(pIO, cBits);
- return uiRet;
- }
- U32 flushToByte(BitIOInfo* pIO)
- {
- return flushBit16(pIO, (16 - pIO->cBitsUsed) & 7);
- }
- #endif // ARMOPT_BITIO
- //----------------------------------------------------------------
- Void putBit16z(BitIOInfo* pIO, U32 uiBits, U32 cBits)
- {
- assert(cBits <= 16);
- assert(0 == uiBits >> cBits);
- pIO->uiAccumulator = (pIO->uiAccumulator << cBits) | uiBits;
- pIO->cBitsUsed += cBits;
- *(U16*)pIO->pbCurrent = (U16)WRITESWAP_ENDIAN(pIO->uiAccumulator << (32 - pIO->cBitsUsed));
- pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3) & 2), pIO->iMask);
- pIO->cBitsUsed &= 16 - 1;
- }
- Void putBit16(BitIOInfo* pIO, U32 uiBits, U32 cBits)
- {
- assert(cBits <= 16);
- uiBits &= ~(-1 << cBits);
- putBit16z(pIO, uiBits, cBits);
- }
- Void putBit32(BitIOInfo* pIO, U32 uiBits, U32 cBits)
- {
- assert(0 <= (I32)cBits && cBits <= 32);
- if (16 < cBits)
- {
- putBit16(pIO, uiBits >> (cBits - 16), 16);
- cBits -= 16;
- }
- putBit16(pIO, uiBits, cBits);
- }
- Void fillToByte(BitIOInfo* pIO)
- {
- putBit16z(pIO, 0, (16 - pIO->cBitsUsed) & 7);
- }
- //----------------------------------------------------------------
- U32 getBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 cBits)
- {
- U32 rc = getBit16(pIO, cBits);
- readIS_L1(pSC, pIO);
- return rc;
- }
- U32 putBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 uiBits, U32 cBits)
- {
- putBit16(pIO, uiBits, cBits);
- writeIS_L1(pSC, pIO);
- return 0;
- }
- //----------------------------------------------------------------
- // Query buffered data size held in BitIOInfo
- // Write() for Enc, Read() for Dec
- //----------------------------------------------------------------
- U32 getSizeRead(BitIOInfo* pIO)
- {
- return (U32)(UINTPTR_T)(pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
- }
- U32 getSizeWrite(BitIOInfo* pIO)
- {
- return (U32)(UINTPTR_T)(pIO->pbCurrent + (pIO->pbStart <= pIO->pbCurrent ? 0 : PACKETLENGTH * 2) - pIO->pbStart) + pIO->cBitsUsed / 8;
- }
- //----------------------------------------------------------------
- // Query stream offset from attached BitIO object for dec
- //----------------------------------------------------------------
- U32 getPosRead(BitIOInfo* pIO)
- {
- size_t cbCached = (pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
- return (U32)(pIO->offRef - cbCached);
- }
- //================================================================
- // Block I/O functions
- //================================================================
- #ifndef ARMOPT_BITIO
- ERR attachISRead(BitIOInfo* pIO, struct WMPStream* pWS, CWMImageStrCodec* pSC)
- {
- UNREFERENCED_PARAMETER( pSC );
- pWS->GetPos(pWS, &pIO->offRef);
- pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
- pIO->pbCurrent = pIO->pbStart;
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- pWS->SetPos(pWS, pIO->offRef);
- pWS->Read(pWS, pIO->pbStart, PACKETLENGTH * 2);
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- pIO->offRef += PACKETLENGTH * 2;
- pIO->uiAccumulator = load4BE(pIO->pbStart);
-
- pIO->cBitsUsed = 0;
- pIO->iMask = ~(PACKETLENGTH * 2);
- pIO->iMask &= ~1;
- pIO->pWS = pWS;
- return WMP_errSuccess;
- }
- ERR readIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
- {
- ERR err = WMP_errSuccess;
- UNREFERENCED_PARAMETER( pSC );
- if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
- {
- struct WMPStream *pWS = pIO->pWS;
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- //Call(0 != pIO->pWS->Read(pIO->pWS, pIO->pbStart, PACKETLENGTH));
- // TODO: add error checking code
- pWS->SetPos(pWS, pIO->offRef);
- pWS->Read(pWS, pIO->pbStart, PACKETLENGTH);
- pIO->offRef += PACKETLENGTH;
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- // make shadow copy for first 4B
- pIO->uiShadow = *(U32*)pIO->pbStart;
- // reposition pbPacket pointer
- pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
- }
- //Cleanup:
- return err;
- }
- ERR detachISRead(CWMImageStrCodec* pSC, BitIOInfo* pIO)
- {
- ERR err = WMP_errSuccess;
- struct WMPStream* pWS = pIO->pWS;
- size_t cbRemain = 0;
- // we can ONLY detach IStream at byte boundary
- flushToByte(pIO);
- assert(0 == (pIO->cBitsUsed % 8));
- Call(readIS_L1(pSC, pIO));
- // set stream to right offset, undo buffering
- cbRemain = (pIO->pbStart + PACKETLENGTH * 2) - (pIO->pbCurrent + pIO->cBitsUsed / 8);
- pWS->SetPos(pWS, pIO->offRef - cbRemain);
- pIO->pWS = NULL;
- Cleanup:
- return err;
- }
- #endif // ARMOPT_BITIO
- //----------------------------------------------------------------
- ERR attachISWrite(BitIOInfo* pIO, struct WMPStream* pWS)
- {
- pWS->GetPos(pWS, &pIO->offRef);
- pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
- pIO->pbCurrent = pIO->pbStart;
- pIO->uiAccumulator = 0;
- pIO->cBitsUsed = 0;
- pIO->iMask = ~(PACKETLENGTH * 2);
- pIO->pWS = pWS;
- return WMP_errSuccess;
- }
- // write out packet if we have >=1 packet data filled
- ERR writeIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
- {
- ERR err = WMP_errSuccess;
- UNREFERENCED_PARAMETER( pSC );
- if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
- {
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, PACKETLENGTH);
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- Call(err);
- // reposition pbStart pointer
- pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
- }
- Cleanup:
- return err;
- }
- // write out partially filled buffer and detach bitIO from IStream
- ERR detachISWrite(CWMImageStrCodec* pSC, BitIOInfo* pIO)
- {
- ERR err = WMP_errSuccess;
- // we can ONLY detach IStream at byte boundary
- assert(0 == (pIO->cBitsUsed % 8));
- Call(writeIS_L1(pSC, pIO));
- PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, pIO->pbCurrent + pIO->cBitsUsed / 8 - pIO->pbStart);
- PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
- Call(err);
- pIO->pWS = NULL;
- Cleanup:
- return err;
- }
- //=========================
- // Performance Measurement
- //=========================
- #ifndef DISABLE_PERF_MEASUREMENT
- void OutputIndivPerfTimer(struct PERFTIMERSTATE *pPerfTimer,
- char *pszTimerName,
- char *pszDescription,
- float fltMegaPixels)
- {
- PERFTIMERRESULTS rResults;
- Bool fResult;
- fResult = FALSE;
- printf("%s (%s): ", pszTimerName, pszDescription);
- if (pPerfTimer)
- {
- fResult = PerfTimerGetResults(pPerfTimer, &rResults);
- if (fResult)
- {
- printf("%.3f milliseconds, %.6f MP/sec\n", (float)rResults.iElapsedTime / 1000000,
- 1000000000 * fltMegaPixels / rResults.iElapsedTime);
- if (rResults.iZeroTimeIntervals > 0)
- {
- printf(" *** WARNING: %d time intervals were measured as zero. "
- "This perf timer has insufficient precision!\n\n",
- (int) rResults.iZeroTimeIntervals);
- }
- }
- }
- if (FALSE == fResult)
- printf("Results not available!\n");
- }
- void OutputPerfTimerReport(CWMImageStrCodec *pState)
- {
- float fltMegaPixels;
- assert(pState->m_fMeasurePerf);
- printf("***************************************************************************\n");
- printf("* Perf Report\n");
- printf("***************************************************************************\n\n");
-
- fltMegaPixels = (float)pState->WMII.cWidth * pState->WMII.cHeight / 1000000;
- printf("Image Width = %d, Height = %d, total MegaPixels = %.1f MP\n",
- (int) pState->WMII.cWidth, (int) pState->WMII.cHeight, fltMegaPixels);
- OutputIndivPerfTimer(pState->m_ptEncDecPerf, "m_ptEncDecPerf", "excl I/O", fltMegaPixels);
- OutputIndivPerfTimer(pState->m_ptEndToEndPerf, "m_ptEndToEndPerf", "incl I/O", fltMegaPixels);
- }
- #endif // DISABLE_PERF_MEASUREMENT
|