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 
EncodeIntraPCM(AVCEncObject * encvid)20 AVCEnc_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 
enc_residual_block(AVCEncObject * encvid,AVCResidualType type,int cindx,AVCMacroblock * currMB)145 AVCEnc_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