129a84457aed4c45bc900998b5e11c03023264208James Dong/* ------------------------------------------------------------------
229a84457aed4c45bc900998b5e11c03023264208James Dong * Copyright (C) 1998-2009 PacketVideo
329a84457aed4c45bc900998b5e11c03023264208James Dong *
429a84457aed4c45bc900998b5e11c03023264208James Dong * Licensed under the Apache License, Version 2.0 (the "License");
529a84457aed4c45bc900998b5e11c03023264208James Dong * you may not use this file except in compliance with the License.
629a84457aed4c45bc900998b5e11c03023264208James Dong * You may obtain a copy of the License at
729a84457aed4c45bc900998b5e11c03023264208James Dong *
829a84457aed4c45bc900998b5e11c03023264208James Dong *      http://www.apache.org/licenses/LICENSE-2.0
929a84457aed4c45bc900998b5e11c03023264208James Dong *
1029a84457aed4c45bc900998b5e11c03023264208James Dong * Unless required by applicable law or agreed to in writing, software
1129a84457aed4c45bc900998b5e11c03023264208James Dong * distributed under the License is distributed on an "AS IS" BASIS,
1229a84457aed4c45bc900998b5e11c03023264208James Dong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1329a84457aed4c45bc900998b5e11c03023264208James Dong * express or implied.
1429a84457aed4c45bc900998b5e11c03023264208James Dong * See the License for the specific language governing permissions
1529a84457aed4c45bc900998b5e11c03023264208James Dong * and limitations under the License.
1629a84457aed4c45bc900998b5e11c03023264208James Dong * -------------------------------------------------------------------
1729a84457aed4c45bc900998b5e11c03023264208James Dong */
1829a84457aed4c45bc900998b5e11c03023264208James Dong#include "avcenc_lib.h"
1929a84457aed4c45bc900998b5e11c03023264208James Dong
2029a84457aed4c45bc900998b5e11c03023264208James DongAVCEnc_Status EncodeIntraPCM(AVCEncObject *encvid)
2129a84457aed4c45bc900998b5e11c03023264208James Dong{
2229a84457aed4c45bc900998b5e11c03023264208James Dong    AVCEnc_Status status = AVCENC_SUCCESS;
2329a84457aed4c45bc900998b5e11c03023264208James Dong    AVCCommonObj *video = encvid->common;
2429a84457aed4c45bc900998b5e11c03023264208James Dong    AVCFrameIO  *currInput = encvid->currInput;
2529a84457aed4c45bc900998b5e11c03023264208James Dong    AVCEncBitstream *stream = encvid->bitstream;
2629a84457aed4c45bc900998b5e11c03023264208James Dong    int x_position = (video->mb_x << 4);
2729a84457aed4c45bc900998b5e11c03023264208James Dong    int y_position = (video->mb_y << 4);
2829a84457aed4c45bc900998b5e11c03023264208James Dong    int orgPitch = currInput->pitch;
2929a84457aed4c45bc900998b5e11c03023264208James Dong    int offset1 = y_position * orgPitch + x_position;
3029a84457aed4c45bc900998b5e11c03023264208James Dong    int i, j;
3129a84457aed4c45bc900998b5e11c03023264208James Dong    int offset;
3229a84457aed4c45bc900998b5e11c03023264208James Dong    uint8 *pDst, *pSrc;
3329a84457aed4c45bc900998b5e11c03023264208James Dong    uint code;
3429a84457aed4c45bc900998b5e11c03023264208James Dong
3529a84457aed4c45bc900998b5e11c03023264208James Dong    ue_v(stream, 25);
3629a84457aed4c45bc900998b5e11c03023264208James Dong
3729a84457aed4c45bc900998b5e11c03023264208James Dong    i = stream->bit_left & 0x7;
3829a84457aed4c45bc900998b5e11c03023264208James Dong    if (i) /* not byte-aligned */
3929a84457aed4c45bc900998b5e11c03023264208James Dong    {
4029a84457aed4c45bc900998b5e11c03023264208James Dong        BitstreamWriteBits(stream, 0, i);
4129a84457aed4c45bc900998b5e11c03023264208James Dong    }
4229a84457aed4c45bc900998b5e11c03023264208James Dong
4329a84457aed4c45bc900998b5e11c03023264208James Dong    pSrc = currInput->YCbCr[0] + offset1;
4429a84457aed4c45bc900998b5e11c03023264208James Dong    pDst = video->currPic->Sl + offset1;
4529a84457aed4c45bc900998b5e11c03023264208James Dong    offset = video->PicWidthInSamplesL - 16;
4629a84457aed4c45bc900998b5e11c03023264208James Dong
4729a84457aed4c45bc900998b5e11c03023264208James Dong    /* at this point bitstream is byte-aligned */
4829a84457aed4c45bc900998b5e11c03023264208James Dong    j = 16;
4929a84457aed4c45bc900998b5e11c03023264208James Dong    while (j > 0)
5029a84457aed4c45bc900998b5e11c03023264208James Dong    {
5129a84457aed4c45bc900998b5e11c03023264208James Dong#if (WORD_SIZE==32)
5229a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 4; i++)
5329a84457aed4c45bc900998b5e11c03023264208James Dong        {
5429a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
5529a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 4;
5629a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
5729a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 4;
5829a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 32, code);
5929a84457aed4c45bc900998b5e11c03023264208James Dong        }
6029a84457aed4c45bc900998b5e11c03023264208James Dong#else
6129a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 8; i++)
6229a84457aed4c45bc900998b5e11c03023264208James Dong        {
6329a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
6429a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 2;
6529a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
6629a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 2;
6729a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 16, code);
6829a84457aed4c45bc900998b5e11c03023264208James Dong        }
6929a84457aed4c45bc900998b5e11c03023264208James Dong#endif
7029a84457aed4c45bc900998b5e11c03023264208James Dong        pDst += offset;
7129a84457aed4c45bc900998b5e11c03023264208James Dong        pSrc += offset;
7229a84457aed4c45bc900998b5e11c03023264208James Dong        j--;
7329a84457aed4c45bc900998b5e11c03023264208James Dong    }
7429a84457aed4c45bc900998b5e11c03023264208James Dong    if (status != AVCENC_SUCCESS)  /* check only once per line */
7529a84457aed4c45bc900998b5e11c03023264208James Dong        return status;
7629a84457aed4c45bc900998b5e11c03023264208James Dong
7729a84457aed4c45bc900998b5e11c03023264208James Dong    pDst = video->currPic->Scb + ((offset1 + x_position) >> 2);
7829a84457aed4c45bc900998b5e11c03023264208James Dong    pSrc = currInput->YCbCr[1] + ((offset1 + x_position) >> 2);
7929a84457aed4c45bc900998b5e11c03023264208James Dong    offset >>= 1;
8029a84457aed4c45bc900998b5e11c03023264208James Dong
8129a84457aed4c45bc900998b5e11c03023264208James Dong    j = 8;
8229a84457aed4c45bc900998b5e11c03023264208James Dong    while (j > 0)
8329a84457aed4c45bc900998b5e11c03023264208James Dong    {
8429a84457aed4c45bc900998b5e11c03023264208James Dong#if (WORD_SIZE==32)
8529a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 2; i++)
8629a84457aed4c45bc900998b5e11c03023264208James Dong        {
8729a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
8829a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 4;
8929a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
9029a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 4;
9129a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 32, code);
9229a84457aed4c45bc900998b5e11c03023264208James Dong        }
9329a84457aed4c45bc900998b5e11c03023264208James Dong#else
9429a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 4; i++)
9529a84457aed4c45bc900998b5e11c03023264208James Dong        {
9629a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
9729a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 2;
9829a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
9929a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 2;
10029a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 16, code);
10129a84457aed4c45bc900998b5e11c03023264208James Dong        }
10229a84457aed4c45bc900998b5e11c03023264208James Dong#endif
10329a84457aed4c45bc900998b5e11c03023264208James Dong        pDst += offset;
10429a84457aed4c45bc900998b5e11c03023264208James Dong        pSrc += offset;
10529a84457aed4c45bc900998b5e11c03023264208James Dong        j--;
10629a84457aed4c45bc900998b5e11c03023264208James Dong    }
10729a84457aed4c45bc900998b5e11c03023264208James Dong
10829a84457aed4c45bc900998b5e11c03023264208James Dong    if (status != AVCENC_SUCCESS)  /* check only once per line */
10929a84457aed4c45bc900998b5e11c03023264208James Dong        return status;
11029a84457aed4c45bc900998b5e11c03023264208James Dong
11129a84457aed4c45bc900998b5e11c03023264208James Dong    pDst = video->currPic->Scr + ((offset1 + x_position) >> 2);
11229a84457aed4c45bc900998b5e11c03023264208James Dong    pSrc = currInput->YCbCr[2] + ((offset1 + x_position) >> 2);
11329a84457aed4c45bc900998b5e11c03023264208James Dong
11429a84457aed4c45bc900998b5e11c03023264208James Dong    j = 8;
11529a84457aed4c45bc900998b5e11c03023264208James Dong    while (j > 0)
11629a84457aed4c45bc900998b5e11c03023264208James Dong    {
11729a84457aed4c45bc900998b5e11c03023264208James Dong#if (WORD_SIZE==32)
11829a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 2; i++)
11929a84457aed4c45bc900998b5e11c03023264208James Dong        {
12029a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
12129a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 4;
12229a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
12329a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 4;
12429a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 32, code);
12529a84457aed4c45bc900998b5e11c03023264208James Dong        }
12629a84457aed4c45bc900998b5e11c03023264208James Dong#else
12729a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = 0; i < 4; i++)
12829a84457aed4c45bc900998b5e11c03023264208James Dong        {
12929a84457aed4c45bc900998b5e11c03023264208James Dong            code = *((uint*)pSrc);
13029a84457aed4c45bc900998b5e11c03023264208James Dong            pSrc += 2;
13129a84457aed4c45bc900998b5e11c03023264208James Dong            *((uint*)pDst) = code;
13229a84457aed4c45bc900998b5e11c03023264208James Dong            pDst += 2;
13329a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, 16, code);
13429a84457aed4c45bc900998b5e11c03023264208James Dong        }
13529a84457aed4c45bc900998b5e11c03023264208James Dong#endif
13629a84457aed4c45bc900998b5e11c03023264208James Dong        pDst += offset;
13729a84457aed4c45bc900998b5e11c03023264208James Dong        pSrc += offset;
13829a84457aed4c45bc900998b5e11c03023264208James Dong        j--;
13929a84457aed4c45bc900998b5e11c03023264208James Dong    }
14029a84457aed4c45bc900998b5e11c03023264208James Dong
14129a84457aed4c45bc900998b5e11c03023264208James Dong    return status;
14229a84457aed4c45bc900998b5e11c03023264208James Dong}
14329a84457aed4c45bc900998b5e11c03023264208James Dong
14429a84457aed4c45bc900998b5e11c03023264208James Dong
14529a84457aed4c45bc900998b5e11c03023264208James DongAVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int cindx, AVCMacroblock *currMB)
14629a84457aed4c45bc900998b5e11c03023264208James Dong{
14729a84457aed4c45bc900998b5e11c03023264208James Dong    AVCEnc_Status status = AVCENC_SUCCESS;
14829a84457aed4c45bc900998b5e11c03023264208James Dong    AVCCommonObj *video = encvid->common;
14929a84457aed4c45bc900998b5e11c03023264208James Dong    int i, maxNumCoeff, nC;
15029a84457aed4c45bc900998b5e11c03023264208James Dong    int cdc = 0, cac = 0;
15129a84457aed4c45bc900998b5e11c03023264208James Dong    int TrailingOnes;
15229a84457aed4c45bc900998b5e11c03023264208James Dong    AVCEncBitstream *stream = encvid->bitstream;
15329a84457aed4c45bc900998b5e11c03023264208James Dong    uint trailing_ones_sign_flag;
15429a84457aed4c45bc900998b5e11c03023264208James Dong    int zerosLeft;
15529a84457aed4c45bc900998b5e11c03023264208James Dong    int *level, *run;
15629a84457aed4c45bc900998b5e11c03023264208James Dong    int TotalCoeff;
15729a84457aed4c45bc900998b5e11c03023264208James Dong    const static int incVlc[] = {0, 3, 6, 12, 24, 48, 32768};  // maximum vlc = 6
15829a84457aed4c45bc900998b5e11c03023264208James Dong    int escape, numPrefix, sufmask, suffix, shift, sign, value, absvalue, vlcnum, level_two_or_higher;
15929a84457aed4c45bc900998b5e11c03023264208James Dong    int bindx = blkIdx2blkXY[cindx>>2][cindx&3] ; // raster scan index
16029a84457aed4c45bc900998b5e11c03023264208James Dong
16129a84457aed4c45bc900998b5e11c03023264208James Dong    switch (type)
16229a84457aed4c45bc900998b5e11c03023264208James Dong    {
16329a84457aed4c45bc900998b5e11c03023264208James Dong        case AVC_Luma:
16429a84457aed4c45bc900998b5e11c03023264208James Dong            maxNumCoeff = 16;
16529a84457aed4c45bc900998b5e11c03023264208James Dong            level = encvid->level[cindx];
16629a84457aed4c45bc900998b5e11c03023264208James Dong            run = encvid->run[cindx];
16729a84457aed4c45bc900998b5e11c03023264208James Dong            TotalCoeff = currMB->nz_coeff[bindx];
16829a84457aed4c45bc900998b5e11c03023264208James Dong            break;
16929a84457aed4c45bc900998b5e11c03023264208James Dong        case AVC_Intra16DC:
17029a84457aed4c45bc900998b5e11c03023264208James Dong            maxNumCoeff = 16;
17129a84457aed4c45bc900998b5e11c03023264208James Dong            level = encvid->leveldc;
17229a84457aed4c45bc900998b5e11c03023264208James Dong            run = encvid->rundc;
17329a84457aed4c45bc900998b5e11c03023264208James Dong            TotalCoeff = cindx; /* special case */
17429a84457aed4c45bc900998b5e11c03023264208James Dong            bindx = 0;
17529a84457aed4c45bc900998b5e11c03023264208James Dong            cindx = 0;
17629a84457aed4c45bc900998b5e11c03023264208James Dong            break;
17729a84457aed4c45bc900998b5e11c03023264208James Dong        case AVC_Intra16AC:
17829a84457aed4c45bc900998b5e11c03023264208James Dong            maxNumCoeff = 15;
17929a84457aed4c45bc900998b5e11c03023264208James Dong            level = encvid->level[cindx];
18029a84457aed4c45bc900998b5e11c03023264208James Dong            run = encvid->run[cindx];
18129a84457aed4c45bc900998b5e11c03023264208James Dong            TotalCoeff = currMB->nz_coeff[bindx];
18229a84457aed4c45bc900998b5e11c03023264208James Dong            break;
18329a84457aed4c45bc900998b5e11c03023264208James Dong        case AVC_ChromaDC:  /* how to differentiate Cb from Cr */
18429a84457aed4c45bc900998b5e11c03023264208James Dong            maxNumCoeff = 4;
18529a84457aed4c45bc900998b5e11c03023264208James Dong            cdc = 1;
18629a84457aed4c45bc900998b5e11c03023264208James Dong            if (cindx >= 8)
18729a84457aed4c45bc900998b5e11c03023264208James Dong            {
18829a84457aed4c45bc900998b5e11c03023264208James Dong                level = encvid->levelcdc + 4;
18929a84457aed4c45bc900998b5e11c03023264208James Dong                run = encvid->runcdc + 4;
19029a84457aed4c45bc900998b5e11c03023264208James Dong                TotalCoeff = cindx - 8;  /* special case */
19129a84457aed4c45bc900998b5e11c03023264208James Dong            }
19229a84457aed4c45bc900998b5e11c03023264208James Dong            else
19329a84457aed4c45bc900998b5e11c03023264208James Dong            {
19429a84457aed4c45bc900998b5e11c03023264208James Dong                level = encvid->levelcdc;
19529a84457aed4c45bc900998b5e11c03023264208James Dong                run = encvid->runcdc;
19629a84457aed4c45bc900998b5e11c03023264208James Dong                TotalCoeff = cindx;  /* special case */
19729a84457aed4c45bc900998b5e11c03023264208James Dong            }
19829a84457aed4c45bc900998b5e11c03023264208James Dong            break;
19929a84457aed4c45bc900998b5e11c03023264208James Dong        case AVC_ChromaAC:
20029a84457aed4c45bc900998b5e11c03023264208James Dong            maxNumCoeff = 15;
20129a84457aed4c45bc900998b5e11c03023264208James Dong            cac = 1;
20229a84457aed4c45bc900998b5e11c03023264208James Dong            level = encvid->level[cindx];
20329a84457aed4c45bc900998b5e11c03023264208James Dong            run = encvid->run[cindx];
20429a84457aed4c45bc900998b5e11c03023264208James Dong            cindx -= 16;
20529a84457aed4c45bc900998b5e11c03023264208James Dong            bindx = 16 + blkIdx2blkXY[cindx>>2][cindx&3];
20629a84457aed4c45bc900998b5e11c03023264208James Dong            cindx += 16;
20729a84457aed4c45bc900998b5e11c03023264208James Dong            TotalCoeff = currMB->nz_coeff[bindx];
20829a84457aed4c45bc900998b5e11c03023264208James Dong            break;
20929a84457aed4c45bc900998b5e11c03023264208James Dong        default:
21029a84457aed4c45bc900998b5e11c03023264208James Dong            return AVCENC_FAIL;
21129a84457aed4c45bc900998b5e11c03023264208James Dong    }
21229a84457aed4c45bc900998b5e11c03023264208James Dong
21329a84457aed4c45bc900998b5e11c03023264208James Dong
21429a84457aed4c45bc900998b5e11c03023264208James Dong    /* find TrailingOnes */
21529a84457aed4c45bc900998b5e11c03023264208James Dong    TrailingOnes = 0;
21629a84457aed4c45bc900998b5e11c03023264208James Dong    zerosLeft = 0;
21729a84457aed4c45bc900998b5e11c03023264208James Dong    i = TotalCoeff - 1;
21829a84457aed4c45bc900998b5e11c03023264208James Dong    nC = 1;
21929a84457aed4c45bc900998b5e11c03023264208James Dong    while (i >= 0)
22029a84457aed4c45bc900998b5e11c03023264208James Dong    {
22129a84457aed4c45bc900998b5e11c03023264208James Dong        zerosLeft += run[i];
22229a84457aed4c45bc900998b5e11c03023264208James Dong        if (nC && (level[i] == 1 || level[i] == -1))
22329a84457aed4c45bc900998b5e11c03023264208James Dong        {
22429a84457aed4c45bc900998b5e11c03023264208James Dong            TrailingOnes++;
22529a84457aed4c45bc900998b5e11c03023264208James Dong        }
22629a84457aed4c45bc900998b5e11c03023264208James Dong        else
22729a84457aed4c45bc900998b5e11c03023264208James Dong        {
22829a84457aed4c45bc900998b5e11c03023264208James Dong            nC = 0;
22929a84457aed4c45bc900998b5e11c03023264208James Dong        }
23029a84457aed4c45bc900998b5e11c03023264208James Dong        i--;
23129a84457aed4c45bc900998b5e11c03023264208James Dong    }
23229a84457aed4c45bc900998b5e11c03023264208James Dong    if (TrailingOnes > 3)
23329a84457aed4c45bc900998b5e11c03023264208James Dong    {
23429a84457aed4c45bc900998b5e11c03023264208James Dong        TrailingOnes = 3; /* clip it */
23529a84457aed4c45bc900998b5e11c03023264208James Dong    }
23629a84457aed4c45bc900998b5e11c03023264208James Dong
23729a84457aed4c45bc900998b5e11c03023264208James Dong    if (!cdc)
23829a84457aed4c45bc900998b5e11c03023264208James Dong    {
23929a84457aed4c45bc900998b5e11c03023264208James Dong        if (!cac)  /* not chroma */
24029a84457aed4c45bc900998b5e11c03023264208James Dong        {
24129a84457aed4c45bc900998b5e11c03023264208James Dong            nC = predict_nnz(video, bindx & 3, bindx >> 2);
24229a84457aed4c45bc900998b5e11c03023264208James Dong        }
24329a84457aed4c45bc900998b5e11c03023264208James Dong        else /* chroma ac but not chroma dc */
24429a84457aed4c45bc900998b5e11c03023264208James Dong        {
24529a84457aed4c45bc900998b5e11c03023264208James Dong            nC = predict_nnz_chroma(video, bindx & 3, bindx >> 2);
24629a84457aed4c45bc900998b5e11c03023264208James Dong        }
24729a84457aed4c45bc900998b5e11c03023264208James Dong
24829a84457aed4c45bc900998b5e11c03023264208James Dong        status = ce_TotalCoeffTrailingOnes(stream, TrailingOnes, TotalCoeff, nC);
24929a84457aed4c45bc900998b5e11c03023264208James Dong    }
25029a84457aed4c45bc900998b5e11c03023264208James Dong    else
25129a84457aed4c45bc900998b5e11c03023264208James Dong    {
25229a84457aed4c45bc900998b5e11c03023264208James Dong        nC = -1; /* Chroma DC level */
25329a84457aed4c45bc900998b5e11c03023264208James Dong        status = ce_TotalCoeffTrailingOnesChromaDC(stream, TrailingOnes, TotalCoeff);
25429a84457aed4c45bc900998b5e11c03023264208James Dong    }
25529a84457aed4c45bc900998b5e11c03023264208James Dong
25629a84457aed4c45bc900998b5e11c03023264208James Dong    /* This part is done quite differently in ReadCoef4x4_CAVLC() */
25729a84457aed4c45bc900998b5e11c03023264208James Dong    if (TotalCoeff > 0)
25829a84457aed4c45bc900998b5e11c03023264208James Dong    {
25929a84457aed4c45bc900998b5e11c03023264208James Dong
26029a84457aed4c45bc900998b5e11c03023264208James Dong        i = TotalCoeff - 1;
26129a84457aed4c45bc900998b5e11c03023264208James Dong
26229a84457aed4c45bc900998b5e11c03023264208James Dong        if (TrailingOnes) /* keep reading the sign of those trailing ones */
26329a84457aed4c45bc900998b5e11c03023264208James Dong        {
26429a84457aed4c45bc900998b5e11c03023264208James Dong            nC = TrailingOnes;
26529a84457aed4c45bc900998b5e11c03023264208James Dong            trailing_ones_sign_flag = 0;
26629a84457aed4c45bc900998b5e11c03023264208James Dong            while (nC)
26729a84457aed4c45bc900998b5e11c03023264208James Dong            {
26829a84457aed4c45bc900998b5e11c03023264208James Dong                trailing_ones_sign_flag <<= 1;
26929a84457aed4c45bc900998b5e11c03023264208James Dong                trailing_ones_sign_flag |= ((uint32)level[i--] >> 31); /* 0 or positive, 1 for negative */
27029a84457aed4c45bc900998b5e11c03023264208James Dong                nC--;
27129a84457aed4c45bc900998b5e11c03023264208James Dong            }
27229a84457aed4c45bc900998b5e11c03023264208James Dong
27329a84457aed4c45bc900998b5e11c03023264208James Dong            /* instead of writing one bit at a time, read the whole thing at once */
27429a84457aed4c45bc900998b5e11c03023264208James Dong            status = BitstreamWriteBits(stream, TrailingOnes, trailing_ones_sign_flag);
27529a84457aed4c45bc900998b5e11c03023264208James Dong        }
27629a84457aed4c45bc900998b5e11c03023264208James Dong
27729a84457aed4c45bc900998b5e11c03023264208James Dong        level_two_or_higher = 1;
27829a84457aed4c45bc900998b5e11c03023264208James Dong        if (TotalCoeff > 3 && TrailingOnes == 3)
27929a84457aed4c45bc900998b5e11c03023264208James Dong        {
28029a84457aed4c45bc900998b5e11c03023264208James Dong            level_two_or_higher = 0;
28129a84457aed4c45bc900998b5e11c03023264208James Dong        }
28229a84457aed4c45bc900998b5e11c03023264208James Dong
28329a84457aed4c45bc900998b5e11c03023264208James Dong        if (TotalCoeff > 10 && TrailingOnes < 3)
28429a84457aed4c45bc900998b5e11c03023264208James Dong        {
28529a84457aed4c45bc900998b5e11c03023264208James Dong            vlcnum = 1;
28629a84457aed4c45bc900998b5e11c03023264208James Dong        }
28729a84457aed4c45bc900998b5e11c03023264208James Dong        else
28829a84457aed4c45bc900998b5e11c03023264208James Dong        {
28929a84457aed4c45bc900998b5e11c03023264208James Dong            vlcnum = 0;
29029a84457aed4c45bc900998b5e11c03023264208James Dong        }
29129a84457aed4c45bc900998b5e11c03023264208James Dong
29229a84457aed4c45bc900998b5e11c03023264208James Dong        /* then do this TotalCoeff-TrailingOnes times */
29329a84457aed4c45bc900998b5e11c03023264208James Dong        for (i = TotalCoeff - TrailingOnes - 1; i >= 0; i--)
29429a84457aed4c45bc900998b5e11c03023264208James Dong        {
29529a84457aed4c45bc900998b5e11c03023264208James Dong            value = level[i];
29629a84457aed4c45bc900998b5e11c03023264208James Dong            absvalue = (value >= 0) ? value : -value;
29729a84457aed4c45bc900998b5e11c03023264208James Dong
29829a84457aed4c45bc900998b5e11c03023264208James Dong            if (level_two_or_higher)
29929a84457aed4c45bc900998b5e11c03023264208James Dong            {
30029a84457aed4c45bc900998b5e11c03023264208James Dong                if (value > 0) value--;
30129a84457aed4c45bc900998b5e11c03023264208James Dong                else    value++;
30229a84457aed4c45bc900998b5e11c03023264208James Dong                level_two_or_higher = 0;
30329a84457aed4c45bc900998b5e11c03023264208James Dong            }
30429a84457aed4c45bc900998b5e11c03023264208James Dong
30529a84457aed4c45bc900998b5e11c03023264208James Dong            if (value >= 0)
30629a84457aed4c45bc900998b5e11c03023264208James Dong            {
30729a84457aed4c45bc900998b5e11c03023264208James Dong                sign = 0;
30829a84457aed4c45bc900998b5e11c03023264208James Dong            }
30929a84457aed4c45bc900998b5e11c03023264208James Dong            else
31029a84457aed4c45bc900998b5e11c03023264208James Dong            {
31129a84457aed4c45bc900998b5e11c03023264208James Dong                sign = 1;
31229a84457aed4c45bc900998b5e11c03023264208James Dong                value = -value;
31329a84457aed4c45bc900998b5e11c03023264208James Dong            }
31429a84457aed4c45bc900998b5e11c03023264208James Dong
31529a84457aed4c45bc900998b5e11c03023264208James Dong            if (vlcnum == 0) // VLC1
31629a84457aed4c45bc900998b5e11c03023264208James Dong            {
31729a84457aed4c45bc900998b5e11c03023264208James Dong                if (value < 8)
31829a84457aed4c45bc900998b5e11c03023264208James Dong                {
31929a84457aed4c45bc900998b5e11c03023264208James Dong                    status = BitstreamWriteBits(stream, value * 2 + sign - 1, 1);
32029a84457aed4c45bc900998b5e11c03023264208James Dong                }
32129a84457aed4c45bc900998b5e11c03023264208James Dong                else if (value < 8 + 8)
32229a84457aed4c45bc900998b5e11c03023264208James Dong                {
32329a84457aed4c45bc900998b5e11c03023264208James Dong                    status = BitstreamWriteBits(stream, 14 + 1 + 4, (1 << 4) | ((value - 8) << 1) | sign);
32429a84457aed4c45bc900998b5e11c03023264208James Dong                }
32529a84457aed4c45bc900998b5e11c03023264208James Dong                else
32629a84457aed4c45bc900998b5e11c03023264208James Dong                {
32729a84457aed4c45bc900998b5e11c03023264208James Dong                    status = BitstreamWriteBits(stream, 14 + 2 + 12, (1 << 12) | ((value - 16) << 1) | sign) ;
32829a84457aed4c45bc900998b5e11c03023264208James Dong                }
32929a84457aed4c45bc900998b5e11c03023264208James Dong            }
33029a84457aed4c45bc900998b5e11c03023264208James Dong            else  // VLCN
33129a84457aed4c45bc900998b5e11c03023264208James Dong            {
33229a84457aed4c45bc900998b5e11c03023264208James Dong                shift = vlcnum - 1;
33329a84457aed4c45bc900998b5e11c03023264208James Dong                escape = (15 << shift) + 1;
33429a84457aed4c45bc900998b5e11c03023264208James Dong                numPrefix = (value - 1) >> shift;
33529a84457aed4c45bc900998b5e11c03023264208James Dong                sufmask = ~((0xffffffff) << shift);
33629a84457aed4c45bc900998b5e11c03023264208James Dong                suffix = (value - 1) & sufmask;
33729a84457aed4c45bc900998b5e11c03023264208James Dong                if (value < escape)
33829a84457aed4c45bc900998b5e11c03023264208James Dong                {
33929a84457aed4c45bc900998b5e11c03023264208James Dong                    status = BitstreamWriteBits(stream, numPrefix + vlcnum + 1, (1 << (shift + 1)) | (suffix << 1) | sign);
34029a84457aed4c45bc900998b5e11c03023264208James Dong                }
34129a84457aed4c45bc900998b5e11c03023264208James Dong                else
34229a84457aed4c45bc900998b5e11c03023264208James Dong                {
34329a84457aed4c45bc900998b5e11c03023264208James Dong                    status = BitstreamWriteBits(stream, 28, (1 << 12) | ((value - escape) << 1) | sign);
34429a84457aed4c45bc900998b5e11c03023264208James Dong                }
34529a84457aed4c45bc900998b5e11c03023264208James Dong
34629a84457aed4c45bc900998b5e11c03023264208James Dong            }
34729a84457aed4c45bc900998b5e11c03023264208James Dong
34829a84457aed4c45bc900998b5e11c03023264208James Dong            if (absvalue > incVlc[vlcnum])
34929a84457aed4c45bc900998b5e11c03023264208James Dong                vlcnum++;
35029a84457aed4c45bc900998b5e11c03023264208James Dong
35129a84457aed4c45bc900998b5e11c03023264208James Dong            if (i == TotalCoeff - TrailingOnes - 1 && absvalue > 3)
35229a84457aed4c45bc900998b5e11c03023264208James Dong                vlcnum = 2;
35329a84457aed4c45bc900998b5e11c03023264208James Dong        }
35429a84457aed4c45bc900998b5e11c03023264208James Dong
35529a84457aed4c45bc900998b5e11c03023264208James Dong        if (status != AVCENC_SUCCESS)  /* occasionally check the bitstream */
35629a84457aed4c45bc900998b5e11c03023264208James Dong        {
35729a84457aed4c45bc900998b5e11c03023264208James Dong            return status;
35829a84457aed4c45bc900998b5e11c03023264208James Dong        }
35929a84457aed4c45bc900998b5e11c03023264208James Dong        if (TotalCoeff < maxNumCoeff)
36029a84457aed4c45bc900998b5e11c03023264208James Dong        {
36129a84457aed4c45bc900998b5e11c03023264208James Dong            if (!cdc)
36229a84457aed4c45bc900998b5e11c03023264208James Dong            {
36329a84457aed4c45bc900998b5e11c03023264208James Dong                ce_TotalZeros(stream, zerosLeft, TotalCoeff);
36429a84457aed4c45bc900998b5e11c03023264208James Dong            }
36529a84457aed4c45bc900998b5e11c03023264208James Dong            else
36629a84457aed4c45bc900998b5e11c03023264208James Dong            {
36729a84457aed4c45bc900998b5e11c03023264208James Dong                ce_TotalZerosChromaDC(stream, zerosLeft, TotalCoeff);
36829a84457aed4c45bc900998b5e11c03023264208James Dong            }
36929a84457aed4c45bc900998b5e11c03023264208James Dong        }
37029a84457aed4c45bc900998b5e11c03023264208James Dong        else
37129a84457aed4c45bc900998b5e11c03023264208James Dong        {
37229a84457aed4c45bc900998b5e11c03023264208James Dong            zerosLeft = 0;
37329a84457aed4c45bc900998b5e11c03023264208James Dong        }
37429a84457aed4c45bc900998b5e11c03023264208James Dong
37529a84457aed4c45bc900998b5e11c03023264208James Dong        i = TotalCoeff - 1;
37629a84457aed4c45bc900998b5e11c03023264208James Dong        while (i > 0) /* don't do the last one */
37729a84457aed4c45bc900998b5e11c03023264208James Dong        {
37829a84457aed4c45bc900998b5e11c03023264208James Dong            if (zerosLeft > 0)
37929a84457aed4c45bc900998b5e11c03023264208James Dong            {
38029a84457aed4c45bc900998b5e11c03023264208James Dong                ce_RunBefore(stream, run[i], zerosLeft);
38129a84457aed4c45bc900998b5e11c03023264208James Dong            }
38229a84457aed4c45bc900998b5e11c03023264208James Dong
38329a84457aed4c45bc900998b5e11c03023264208James Dong            zerosLeft = zerosLeft - run[i];
38429a84457aed4c45bc900998b5e11c03023264208James Dong            i--;
38529a84457aed4c45bc900998b5e11c03023264208James Dong        }
38629a84457aed4c45bc900998b5e11c03023264208James Dong    }
38729a84457aed4c45bc900998b5e11c03023264208James Dong
38829a84457aed4c45bc900998b5e11c03023264208James Dong    return status;
38929a84457aed4c45bc900998b5e11c03023264208James Dong}
390