Home | History | Annotate | Download | only in src
      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 
     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 
    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