residual.cpp revision 29a84457aed4c45bc900998b5e11c03023264208
1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18#include "avcenc_lib.h"
19
20AVCEnc_Status EncodeIntraPCM(AVCEncObject *encvid)
21{
22    AVCEnc_Status status = AVCENC_SUCCESS;
23    AVCCommonObj *video = encvid->common;
24    AVCFrameIO  *currInput = encvid->currInput;
25    AVCEncBitstream *stream = encvid->bitstream;
26    int x_position = (video->mb_x << 4);
27    int y_position = (video->mb_y << 4);
28    int orgPitch = currInput->pitch;
29    int offset1 = y_position * orgPitch + x_position;
30    int i, j;
31    int offset;
32    uint8 *pDst, *pSrc;
33    uint code;
34
35    ue_v(stream, 25);
36
37    i = stream->bit_left & 0x7;
38    if (i) /* not byte-aligned */
39    {
40        BitstreamWriteBits(stream, 0, i);
41    }
42
43    pSrc = currInput->YCbCr[0] + offset1;
44    pDst = video->currPic->Sl + offset1;
45    offset = video->PicWidthInSamplesL - 16;
46
47    /* at this point bitstream is byte-aligned */
48    j = 16;
49    while (j > 0)
50    {
51#if (WORD_SIZE==32)
52        for (i = 0; i < 4; i++)
53        {
54            code = *((uint*)pSrc);
55            pSrc += 4;
56            *((uint*)pDst) = code;
57            pDst += 4;
58            status = BitstreamWriteBits(stream, 32, code);
59        }
60#else
61        for (i = 0; i < 8; i++)
62        {
63            code = *((uint*)pSrc);
64            pSrc += 2;
65            *((uint*)pDst) = code;
66            pDst += 2;
67            status = BitstreamWriteBits(stream, 16, code);
68        }
69#endif
70        pDst += offset;
71        pSrc += offset;
72        j--;
73    }
74    if (status != AVCENC_SUCCESS)  /* check only once per line */
75        return status;
76
77    pDst = video->currPic->Scb + ((offset1 + x_position) >> 2);
78    pSrc = currInput->YCbCr[1] + ((offset1 + x_position) >> 2);
79    offset >>= 1;
80
81    j = 8;
82    while (j > 0)
83    {
84#if (WORD_SIZE==32)
85        for (i = 0; i < 2; i++)
86        {
87            code = *((uint*)pSrc);
88            pSrc += 4;
89            *((uint*)pDst) = code;
90            pDst += 4;
91            status = BitstreamWriteBits(stream, 32, code);
92        }
93#else
94        for (i = 0; i < 4; i++)
95        {
96            code = *((uint*)pSrc);
97            pSrc += 2;
98            *((uint*)pDst) = code;
99            pDst += 2;
100            status = BitstreamWriteBits(stream, 16, code);
101        }
102#endif
103        pDst += offset;
104        pSrc += offset;
105        j--;
106    }
107
108    if (status != AVCENC_SUCCESS)  /* check only once per line */
109        return status;
110
111    pDst = video->currPic->Scr + ((offset1 + x_position) >> 2);
112    pSrc = currInput->YCbCr[2] + ((offset1 + x_position) >> 2);
113
114    j = 8;
115    while (j > 0)
116    {
117#if (WORD_SIZE==32)
118        for (i = 0; i < 2; i++)
119        {
120            code = *((uint*)pSrc);
121            pSrc += 4;
122            *((uint*)pDst) = code;
123            pDst += 4;
124            status = BitstreamWriteBits(stream, 32, code);
125        }
126#else
127        for (i = 0; i < 4; i++)
128        {
129            code = *((uint*)pSrc);
130            pSrc += 2;
131            *((uint*)pDst) = code;
132            pDst += 2;
133            status = BitstreamWriteBits(stream, 16, code);
134        }
135#endif
136        pDst += offset;
137        pSrc += offset;
138        j--;
139    }
140
141    return status;
142}
143
144
145AVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int cindx, AVCMacroblock *currMB)
146{
147    AVCEnc_Status status = AVCENC_SUCCESS;
148    AVCCommonObj *video = encvid->common;
149    int i, maxNumCoeff, nC;
150    int cdc = 0, cac = 0;
151    int TrailingOnes;
152    AVCEncBitstream *stream = encvid->bitstream;
153    uint trailing_ones_sign_flag;
154    int zerosLeft;
155    int *level, *run;
156    int TotalCoeff;
157    const static int incVlc[] = {0, 3, 6, 12, 24, 48, 32768};  // maximum vlc = 6
158    int escape, numPrefix, sufmask, suffix, shift, sign, value, absvalue, vlcnum, level_two_or_higher;
159    int bindx = blkIdx2blkXY[cindx>>2][cindx&3] ; // raster scan index
160
161    switch (type)
162    {
163        case AVC_Luma:
164            maxNumCoeff = 16;
165            level = encvid->level[cindx];
166            run = encvid->run[cindx];
167            TotalCoeff = currMB->nz_coeff[bindx];
168            break;
169        case AVC_Intra16DC:
170            maxNumCoeff = 16;
171            level = encvid->leveldc;
172            run = encvid->rundc;
173            TotalCoeff = cindx; /* special case */
174            bindx = 0;
175            cindx = 0;
176            break;
177        case AVC_Intra16AC:
178            maxNumCoeff = 15;
179            level = encvid->level[cindx];
180            run = encvid->run[cindx];
181            TotalCoeff = currMB->nz_coeff[bindx];
182            break;
183        case AVC_ChromaDC:  /* how to differentiate Cb from Cr */
184            maxNumCoeff = 4;
185            cdc = 1;
186            if (cindx >= 8)
187            {
188                level = encvid->levelcdc + 4;
189                run = encvid->runcdc + 4;
190                TotalCoeff = cindx - 8;  /* special case */
191            }
192            else
193            {
194                level = encvid->levelcdc;
195                run = encvid->runcdc;
196                TotalCoeff = cindx;  /* special case */
197            }
198            break;
199        case AVC_ChromaAC:
200            maxNumCoeff = 15;
201            cac = 1;
202            level = encvid->level[cindx];
203            run = encvid->run[cindx];
204            cindx -= 16;
205            bindx = 16 + blkIdx2blkXY[cindx>>2][cindx&3];
206            cindx += 16;
207            TotalCoeff = currMB->nz_coeff[bindx];
208            break;
209        default:
210            return AVCENC_FAIL;
211    }
212
213
214    /* find TrailingOnes */
215    TrailingOnes = 0;
216    zerosLeft = 0;
217    i = TotalCoeff - 1;
218    nC = 1;
219    while (i >= 0)
220    {
221        zerosLeft += run[i];
222        if (nC && (level[i] == 1 || level[i] == -1))
223        {
224            TrailingOnes++;
225        }
226        else
227        {
228            nC = 0;
229        }
230        i--;
231    }
232    if (TrailingOnes > 3)
233    {
234        TrailingOnes = 3; /* clip it */
235    }
236
237    if (!cdc)
238    {
239        if (!cac)  /* not chroma */
240        {
241            nC = predict_nnz(video, bindx & 3, bindx >> 2);
242        }
243        else /* chroma ac but not chroma dc */
244        {
245            nC = predict_nnz_chroma(video, bindx & 3, bindx >> 2);
246        }
247
248        status = ce_TotalCoeffTrailingOnes(stream, TrailingOnes, TotalCoeff, nC);
249    }
250    else
251    {
252        nC = -1; /* Chroma DC level */
253        status = ce_TotalCoeffTrailingOnesChromaDC(stream, TrailingOnes, TotalCoeff);
254    }
255
256    /* This part is done quite differently in ReadCoef4x4_CAVLC() */
257    if (TotalCoeff > 0)
258    {
259
260        i = TotalCoeff - 1;
261
262        if (TrailingOnes) /* keep reading the sign of those trailing ones */
263        {
264            nC = TrailingOnes;
265            trailing_ones_sign_flag = 0;
266            while (nC)
267            {
268                trailing_ones_sign_flag <<= 1;
269                trailing_ones_sign_flag |= ((uint32)level[i--] >> 31); /* 0 or positive, 1 for negative */
270                nC--;
271            }
272
273            /* instead of writing one bit at a time, read the whole thing at once */
274            status = BitstreamWriteBits(stream, TrailingOnes, trailing_ones_sign_flag);
275        }
276
277        level_two_or_higher = 1;
278        if (TotalCoeff > 3 && TrailingOnes == 3)
279        {
280            level_two_or_higher = 0;
281        }
282
283        if (TotalCoeff > 10 && TrailingOnes < 3)
284        {
285            vlcnum = 1;
286        }
287        else
288        {
289            vlcnum = 0;
290        }
291
292        /* then do this TotalCoeff-TrailingOnes times */
293        for (i = TotalCoeff - TrailingOnes - 1; i >= 0; i--)
294        {
295            value = level[i];
296            absvalue = (value >= 0) ? value : -value;
297
298            if (level_two_or_higher)
299            {
300                if (value > 0) value--;
301                else    value++;
302                level_two_or_higher = 0;
303            }
304
305            if (value >= 0)
306            {
307                sign = 0;
308            }
309            else
310            {
311                sign = 1;
312                value = -value;
313            }
314
315            if (vlcnum == 0) // VLC1
316            {
317                if (value < 8)
318                {
319                    status = BitstreamWriteBits(stream, value * 2 + sign - 1, 1);
320                }
321                else if (value < 8 + 8)
322                {
323                    status = BitstreamWriteBits(stream, 14 + 1 + 4, (1 << 4) | ((value - 8) << 1) | sign);
324                }
325                else
326                {
327                    status = BitstreamWriteBits(stream, 14 + 2 + 12, (1 << 12) | ((value - 16) << 1) | sign) ;
328                }
329            }
330            else  // VLCN
331            {
332                shift = vlcnum - 1;
333                escape = (15 << shift) + 1;
334                numPrefix = (value - 1) >> shift;
335                sufmask = ~((0xffffffff) << shift);
336                suffix = (value - 1) & sufmask;
337                if (value < escape)
338                {
339                    status = BitstreamWriteBits(stream, numPrefix + vlcnum + 1, (1 << (shift + 1)) | (suffix << 1) | sign);
340                }
341                else
342                {
343                    status = BitstreamWriteBits(stream, 28, (1 << 12) | ((value - escape) << 1) | sign);
344                }
345
346            }
347
348            if (absvalue > incVlc[vlcnum])
349                vlcnum++;
350
351            if (i == TotalCoeff - TrailingOnes - 1 && absvalue > 3)
352                vlcnum = 2;
353        }
354
355        if (status != AVCENC_SUCCESS)  /* occasionally check the bitstream */
356        {
357            return status;
358        }
359        if (TotalCoeff < maxNumCoeff)
360        {
361            if (!cdc)
362            {
363                ce_TotalZeros(stream, zerosLeft, TotalCoeff);
364            }
365            else
366            {
367                ce_TotalZerosChromaDC(stream, zerosLeft, TotalCoeff);
368            }
369        }
370        else
371        {
372            zerosLeft = 0;
373        }
374
375        i = TotalCoeff - 1;
376        while (i > 0) /* don't do the last one */
377        {
378            if (zerosLeft > 0)
379            {
380                ce_RunBefore(stream, run[i], zerosLeft);
381            }
382
383            zerosLeft = zerosLeft - run[i];
384            i--;
385        }
386    }
387
388    return status;
389}
390