1 //*@@@+++@@@@******************************************************************
2 //
3 // Copyright � Microsoft Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 //
9 // � Redistributions of source code must retain the above copyright notice,
10 //   this list of conditions and the following disclaimer.
11 // � Redistributions in binary form must reproduce the above copyright notice,
12 //   this list of conditions and the following disclaimer in the documentation
13 //   and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 // POSSIBILITY OF SUCH DAMAGE.
26 //
27 //*@@@---@@@@******************************************************************
28 
29 #include "strcodec.h"
30 
31 #define ORIENT_WEIGHT 4
32 
33 /* reciprocal (pMantissa, exponent) lookup table */
34 typedef struct tagQPManExp
35 {
36     int iMan;
37     int iExp;
38 } QPManExp;
39 
40 static QPManExp gs_QPRecipTable[32] = {
41     {0x0, 0}, // 0, invalid
42     {0x0, 0}, // 1, lossless
43     {0x0, 1}, // 2
44     {0xaaaaaaab, 1},
45     {0x0, 2}, // 4
46     {0xcccccccd, 2},
47     {0xaaaaaaab, 2},
48     {0x92492493, 2},
49     {0x0, 3}, // 8
50     {0xe38e38e4, 3},
51     {0xcccccccd, 3},
52     {0xba2e8ba3, 3},
53     {0xaaaaaaab, 3},
54     {0x9d89d89e, 3},
55     {0x92492493, 3},
56     {0x88888889, 3},
57     {0x0, 4}, // 16
58     {0xf0f0f0f1, 4},
59     {0xe38e38e4, 4},
60     {0xd79435e6, 4},
61     {0xcccccccd, 4},
62     {0xc30c30c4, 4},
63     {0xba2e8ba3, 4},
64     {0xb21642c9, 4},
65     {0xaaaaaaab, 4},
66     {0xa3d70a3e, 4},
67     {0x9d89d89e, 4},
68     {0x97b425ee, 4},
69     {0x92492493, 4},
70     {0x8d3dcb09, 4},
71     {0x88888889, 4},
72     {0x84210843, 4},
73 };
74 
75 /*************************************************************************
76     QPRemapping
77 *************************************************************************/
78 
remapQP(CWMIQuantizer * pQP,I32 iShift,Bool bScaledArith)79 Void remapQP(CWMIQuantizer * pQP, I32 iShift, Bool bScaledArith)
80 {
81     U8 uiQPIndex = pQP->iIndex;
82 
83     if(uiQPIndex == 0) // Lossless mode!
84         pQP->iQP = 1, pQP->iMan = pQP->iExp = pQP->iOffset = 0;
85     else if (!bScaledArith) {
86         I32 man = 0, exp = 0;
87         const I32 ciShift = SHIFTZERO - (SHIFTZERO + QPFRACBITS); // == -QPFRACBITS
88 
89         if (pQP->iIndex < 32)
90             man = (pQP->iIndex + 3) >> 2, exp = ciShift + 2;
91         else if (pQP->iIndex < 48)
92             man = (16 + (pQP->iIndex & 0xf) + 1) >> 1, exp = ((pQP->iIndex >> 4) - 1) + 1 + ciShift;
93         else
94             man = 16 + (pQP->iIndex & 0xf), exp = ((pQP->iIndex >> 4) - 1) + ciShift;
95 
96         pQP->iQP = man << exp;
97         pQP->iMan = gs_QPRecipTable[man].iMan;
98         pQP->iExp = gs_QPRecipTable[man].iExp + exp;
99         pQP->iOffset = ((pQP->iQP * 3 + 1) >> 3);
100 #if defined(WMP_OPT_QT)
101         pQP->f1_QP = 1.0f / pQP->iQP;
102         pQP->d1_QP = 1.0 / pQP->iQP;
103 #endif
104     }
105     else {
106         I32 man = 0, exp = 0;
107 
108         if(pQP->iIndex < 16)
109             man = pQP->iIndex, exp = iShift;
110         else
111             man = 16 + (pQP->iIndex & 0xf), exp = ((pQP->iIndex >> 4) - 1) + iShift;
112 
113         pQP->iQP = man << exp;
114         pQP->iMan = gs_QPRecipTable[man].iMan;
115         pQP->iExp = gs_QPRecipTable[man].iExp + exp;
116         pQP->iOffset = ((pQP->iQP * 3 + 1) >> 3);
117 #if defined(WMP_OPT_QT)
118         pQP->f1_QP = 1.0f / pQP->iQP;
119         pQP->d1_QP = 1.0 / pQP->iQP;
120 #endif
121     }
122 }
123 
124 /* allocate PredInfo buffers */
allocatePredInfo(CWMImageStrCodec * pSC)125 Int allocatePredInfo(CWMImageStrCodec *pSC)
126 {
127     size_t i, j;
128     // COLORFORMAT cf = pSC->m_param.cfColorFormat;
129     const size_t mbWidth = pSC->cmbWidth;
130     const size_t iChannels = pSC->m_param.cNumChannels;
131     CWMIPredInfo* pMemory;
132     Bool b32Bit = sizeof(size_t) == 4;
133 
134     if(b32Bit) // integer overlow/underflow check for 32-bit system
135         if(((mbWidth >> 16) * iChannels * 2 * sizeof(CWMIPredInfo)) & 0xffff0000)
136             return ICERR_ERROR;
137     pMemory = (CWMIPredInfo *)malloc(mbWidth * iChannels * 2 * sizeof(CWMIPredInfo));
138     if (pMemory == NULL)
139         return ICERR_ERROR;
140 
141     pSC->pPredInfoMemory = pMemory;
142     for(i = 0; i < iChannels; i ++){
143         pSC->PredInfo[i] = pMemory;
144         pMemory += mbWidth;
145         pSC->PredInfoPrevRow[i] = pMemory;
146         pMemory += mbWidth;
147 
148         for(j = 0; j < mbWidth; j ++){
149             pSC->PredInfo[i][j].piAD = pSC->PredInfo[i][j].iAD;
150             pSC->PredInfoPrevRow[i][j].piAD = pSC->PredInfoPrevRow[i][j].iAD;
151         }
152     }
153 
154     return ICERR_OK;
155 }
156 
157 /* clear PredInfo buffers */
freePredInfo(CWMImageStrCodec * pSC)158 Void freePredInfo(CWMImageStrCodec *pSC)
159 {
160     if (pSC->pPredInfoMemory)
161         free (pSC->pPredInfoMemory);
162     pSC->pPredInfoMemory = NULL;
163 }
164 
165 /* get AC prediction mode: 0(from left) 1(from top) 2(none) */
getACPredMode(CWMIMBInfo * pMBInfo,COLORFORMAT cf)166 Int getACPredMode(CWMIMBInfo * pMBInfo, COLORFORMAT cf)
167 {
168     //Int blkIdx = (cf == Y_ONLY ? 16 : (cf == YUV_420 ? 24 : (cf == YUV_422 ? 32 : 48)));
169     PixelI * pCoeffs = pMBInfo->iBlockDC[0];
170     Int StrH = abs(pCoeffs[1]) + abs(pCoeffs[2]) + abs(pCoeffs[3]);
171     Int StrV = abs(pCoeffs[4]) + abs(pCoeffs[8]) + abs(pCoeffs[12]);
172 
173     if(cf != Y_ONLY && cf != NCOMPONENT){
174         PixelI * pCoeffsU = pMBInfo->iBlockDC[1];
175         PixelI * pCoeffsV = pMBInfo->iBlockDC[2];
176 
177         StrH += abs(pCoeffsU[1]) + abs(pCoeffsV[1]);
178         if(cf == YUV_420){
179             StrV += abs(pCoeffsU[2]) + abs(pCoeffsV[2]);
180         }
181         else if (cf == YUV_422){
182             StrV += abs(pCoeffsU[2]) + abs(pCoeffsV[2]) + abs(pCoeffsU[6]) + abs(pCoeffsV[6]);
183             StrH += abs(pCoeffsU[5]) + abs(pCoeffsV[5]);
184         }
185         else { // YUV_444 or CMYK
186             StrV += abs(pCoeffsU[4]) + abs(pCoeffsV[4]);
187         }
188     }
189 
190     return (StrH * ORIENT_WEIGHT < StrV ? 1 : (StrV * ORIENT_WEIGHT < StrH ? 0 : 2));
191 }
192 
193 /* get DCAC prediction mode: 0(from left) 1(from top) 2(none) */
getDCACPredMode(CWMImageStrCodec * pSC,size_t mbX)194 Int getDCACPredMode(CWMImageStrCodec *pSC, size_t mbX)
195 {
196     Int iDCMode, iADMode = 2;  // DC: 0(left) 1(top) 2(mean) 3(no)
197                                // AD: 0(left) 1(top) 2(no)
198 
199     if(pSC->m_bCtxLeft && pSC->m_bCtxTop){ // topleft corner, no prediction
200         iDCMode = 3;
201     }
202     else if(pSC->m_bCtxLeft){
203         iDCMode = 1; // left column, predict from top
204     }
205     else if(pSC->m_bCtxTop){
206         iDCMode = 0; // top row, predict from left
207     }
208     else{
209         COLORFORMAT cf = pSC->m_param.cfColorFormat;
210         Int iL = pSC->PredInfo[0][mbX - 1].iDC, iT = pSC->PredInfoPrevRow[0][mbX].iDC, iTL = pSC->PredInfoPrevRow[0][mbX - 1].iDC;
211         Int StrH, StrV;
212 
213         if(cf == Y_ONLY || cf == NCOMPONENT){ // CMYK uses YUV metric
214             StrH = abs(iTL - iL);
215             StrV = abs(iTL - iT);
216         }
217         else{
218             CWMIPredInfo * pTU = pSC->PredInfoPrevRow[1] + mbX, * pLU = pSC->PredInfo[1] + mbX - 1, * pTLU = pTU - 1;
219             CWMIPredInfo * pTV = pSC->PredInfoPrevRow[2] + mbX, * pLV = pSC->PredInfo[2] + mbX - 1, * pTLV = pTV - 1;
220             Int scale = (cf == YUV_420 ? 8 : (cf == YUV_422 ? 4 : 2));
221 
222             StrH = abs(iTL - iL) * scale + abs(pTLU->iDC - pLU->iDC) + abs(pTLV->iDC - pLV->iDC);
223             StrV = abs(iTL - iT) * scale + abs(pTLU->iDC - pTU->iDC) + abs(pTLV->iDC - pTV->iDC);
224         }
225         iDCMode = (StrH * ORIENT_WEIGHT < StrV ? 1 : (StrV * ORIENT_WEIGHT < StrH ? 0 : 2));
226     }
227 
228     if(iDCMode == 1 && pSC->MBInfo.iQIndexLP == pSC->PredInfoPrevRow[0][mbX].iQPIndex)
229         iADMode = 1;
230     if(iDCMode == 0 && pSC->MBInfo.iQIndexLP == pSC->PredInfo[0][mbX - 1].iQPIndex)
231         iADMode = 0;
232 
233     return (iDCMode + (iADMode << 2));
234 }
235 
copyAC(PixelI * src,PixelI * dst)236 Void copyAC(PixelI * src, PixelI * dst)
237 {
238     /* first row of ACs */
239     dst[0] = src[1];
240     dst[1] = src[2];
241     dst[2] = src[3];
242 
243     /* first column of ACs */
244     dst[3] = src[4];
245     dst[4] = src[8];
246     dst[5] = src[12];
247 }
248 
249 /* info of current MB to be saved for future prediction */
updatePredInfo(CWMImageStrCodec * pSC,CWMIMBInfo * pMBInfo,size_t mbX,COLORFORMAT cf)250 Void updatePredInfo(CWMImageStrCodec *pSC, CWMIMBInfo * pMBInfo, size_t mbX, COLORFORMAT cf)
251 {
252     CWMIPredInfo *pPredInfo;
253     PixelI * p;
254     Int  i, iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels;
255 
256     for(i = 0; i < iChannels; i ++){
257         pPredInfo = pSC->PredInfo[i] + mbX;
258         p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i];
259 
260         /* DC of DC block */
261         pPredInfo->iDC = p[0];
262 
263         /* QP Index */
264         pPredInfo->iQPIndex = pMBInfo->iQIndexLP;
265 
266         /* first row and first column of ACs of DC block */
267         copyAC(p, pPredInfo->piAD);
268     }
269 
270     if(cf == YUV_420){ // 420 UV channels
271         for(i = 1U; i < 3U; i ++){
272             pPredInfo = pSC->PredInfo[i] + mbX;
273             p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i];
274 
275             /* DC of DC block */
276             pPredInfo->iDC = p[0];
277 
278             /* QP Index */
279             pPredInfo->iQPIndex = pMBInfo->iQIndexLP;
280             /* first row and first column of ACs of DC block */
281             pPredInfo->piAD[0] = p[1];
282             pPredInfo->piAD[1] = p[2];
283         }
284     }
285     else if(cf == YUV_422){ // 420 UV channels
286         for(i = 1U; i < 3U; i ++){
287             pPredInfo = pSC->PredInfo[i] + mbX;
288 
289             /* QP Index */
290             pPredInfo->iQPIndex = pMBInfo->iQIndexLP;
291 
292             p = pMBInfo->iBlockDC[i];//[dcBlkIdx + i];
293 
294             /* DC of DC block */
295             pPredInfo->iDC = p[0];
296 
297             /* first row and first column of ACs of first DC block */
298             pPredInfo->piAD[0] = p[1];
299             pPredInfo->piAD[1] = p[2];
300             /* first row and first column of ACs of second DC block */
301             pPredInfo->piAD[2] = p[5];
302             pPredInfo->piAD[3] = p[6];
303             pPredInfo->piAD[4] = p[4]; //AC of 1D HT!!!
304         }
305     }
306 }
307