Ticket #8545: dxa_v2.patch

File dxa_v2.patch, 6.1 KB (added by Kirben, 13 years ago)

Patch against current SVN

  • encode_dxa.cpp

     
    3535
    3636#define  BUFFER_LEN     1024
    3737
     38// other block dimensions than 4x4 are not really supported yet
     39#define  BLOCKW         4
     40#define  BLOCKH         4
     41
    3842static CompressMode gCompMode = kMP3Mode;
    3943
    4044class DxaEncoder {
     
    4347        int _width, _height, _framerate, _framecount;
    4448        uint8 *_prevframe, *_prevpalette;
    4549
     50        bool m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2);
     51        bool m12blockIsSolidColor(byte *frame, int x, int y, byte &color);
     52        void m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]);
     53        bool m12motionVector(byte *frame, int x, int y, int &mx, int &my);
     54        uLong m12encode(byte *frame, byte *outbuf);
     55
    4656public:
    4757        DxaEncoder(char *filename, int width, int height, int fps);
    4858        ~DxaEncoder();
     
    111121                if (_framecount == 0)
    112122                        compType = 2;
    113123                else
    114                         compType = 3;
     124                        //compType = 3;
     125                        compType = 12;
    115126
    116127                switch (compType) {
    117128                case 2:
     
    169180
    170181                                break;
    171182                        }
     183                case 12:
     184
     185                        {
     186
     187                                uLong outsize1 = _width * _height;
     188                                uLong outsize2 = outsize1;
     189                                uLong outsize3 = outsize1*2;
     190                                uLong outsize4 = outsize1;
     191                                uLong outsize;
     192                                uint8 *outbuf;
     193                                uint8 *outbuf1 = new uint8[outsize1];
     194                                uint8 *outbuf2 = new uint8[outsize2];
     195                                uint8 *outbuf3 = new uint8[outsize3];
     196                                uint8 *outbuf4 = new uint8[outsize4];
     197                                uint8 *xorbuf = new uint8[_width * _height];
     198
     199                                for (int i = 0; i < _width * _height; i++)
     200                                        xorbuf[i] = _prevframe[i] ^ frame[i];
     201
     202                                compress2(outbuf1, &outsize1, xorbuf, _width * _height, 9);
     203                                compress2(outbuf2, &outsize2, frame, _width * _height, 9);
     204                                if (outsize1 < outsize2) {
     205                                        compType = 3;
     206                                        outsize = outsize1;
     207                                        outbuf = outbuf1;
     208                                } else {
     209                                        compType = 2;
     210                                        outsize = outsize2;
     211                                        outbuf = outbuf2;
     212                                }
     213
     214                                outsize3 = m12encode(frame, outbuf3);
     215
     216                                compress2(outbuf4, &outsize4, outbuf3, outsize3, 9);
     217
     218                                if (outsize4 < outsize) {
     219                                        compType = 12;
     220                                        outsize = outsize4;
     221                                        outbuf = outbuf4;
     222                                }
     223
     224                                writeByte(_dxa, compType);
     225                                writeUint32BE(_dxa, outsize);
     226                                fwrite(outbuf, outsize, 1, _dxa);
     227
     228                                delete[] outbuf1;
     229                                delete[] outbuf2;
     230                                delete[] outbuf3;
     231                                delete[] outbuf4;
     232                                delete[] xorbuf;
     233
     234                                break;
     235                        }
    172236                }
    173237
    174238                memcpy(_prevframe, frame, _width * _height);
     
    180244        _framecount++;
    181245}
    182246
     247bool DxaEncoder::m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2) {
     248        byte *b1 = _prevframe + x + y * _width;
     249        byte *b2 = frame + x2 + y2 * _width;
     250        for (int yc = 0; yc < BLOCKH; yc++) {
     251                if (memcmp(b1, b2, BLOCKW))
     252                        return false;
     253                b1 += _width;
     254                b2 += _width;
     255        }
     256        return true;
     257}
     258
     259bool DxaEncoder::m12blockIsSolidColor(byte *frame, int x, int y, byte &color) {
     260        byte *b2 = frame + x + y * _width;
     261        color = *b2;
     262        for (int yc = 0; yc < BLOCKH; yc++) {
     263                for (int xc = 0; xc < BLOCKW; xc++) {
     264                        if (b2[xc] != color)
     265                                return false;
     266                }
     267                b2 += _width;
     268        }
     269        return true;
     270}
     271
     272void DxaEncoder::m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]) {
     273        byte *b1 = _prevframe + x + y * _width;
     274        byte *b2 = frame + x + y * _width;
     275        diffCount = 0;
     276        diffMap = 0;
     277        for (int yc = 0; yc < BLOCKH; yc++) {
     278                for (int xc = 0; xc < BLOCKW; xc++) {
     279                        if (b1[xc] != b2[xc]) {
     280                                diffMap = (diffMap << 1) | 1;
     281                                diffPix[diffCount++] = b2[xc];
     282                        } else {
     283                                diffMap = (diffMap << 1) | 0;
     284                        }
     285                }
     286                b1 += _width;
     287                b2 += _width;
     288        }
     289}
     290
     291bool DxaEncoder::m12motionVector(byte *frame, int x, int y, int &mx, int &my) {
     292        int xmin = (0 > x-7) ? 0 : x-7;
     293        int ymin = (0 > y-7) ? 0 : y-7;
     294        int xmax = (_width < x+8) ? _width : x+8;
     295        int ymax = (_height < y+8) ? _height : y+8;
     296        for (int yc = ymin; yc < ymax; yc++) {
     297                for (int xc = xmin; xc < xmax; xc++) {
     298                        if (m12blocksAreEqual(frame, xc, yc, x, y)) {
     299                                mx = xc - x;
     300                                my = yc - y;
     301                                return true;
     302                        }
     303                }
     304        }
     305        return false;
     306}
     307
     308uLong DxaEncoder::m12encode(byte *frame, byte *outbuf) {
     309        byte *outb = outbuf;
     310        byte color;
     311        int mx, my;
     312        unsigned short diffMap;
     313        int diffCount;
     314        byte diffPix[BLOCKW*BLOCKH];
     315
     316        for (int by = 0; by < _height; by += BLOCKH) {
     317                for (int bx = 0; bx < _width; bx += BLOCKW) {
     318                        if (m12blocksAreEqual(frame, bx, by, bx, by)) {
     319                                *outb++ = 0;
     320                                continue;
     321                        }
     322
     323                        if (m12blockIsSolidColor(frame, bx, by, color)) {
     324                                *outb++ = 2;
     325                                *outb++ = color;
     326                                continue;
     327                        }
     328
     329                        if (m12motionVector(frame, bx, by, mx, my)) {
     330                                byte mbyte = 0;
     331                                if (mx < 0) mbyte |= 0x80;
     332                                mbyte |= (abs(mx) & 7) << 4;
     333                                if (my < 0) mbyte |= 0x08;
     334                                mbyte |= abs(my) & 7;
     335                                *outb++ = 4;
     336                                *outb++ = mbyte;
     337                                continue;
     338                        }
     339
     340                        m12blockDelta(frame, bx, by, diffMap, diffCount, diffPix);
     341
     342                        if (diffCount >= 14) {
     343                                // in this case we store all 16 pixels
     344                                *outb++ = 3;
     345                                byte *b2 = (byte*)frame + bx + by * _width;
     346                                for (int yc = 0; yc < BLOCKH; yc++) {
     347                                        memcpy(outb, b2, BLOCKW);
     348                                        b2 += _width;
     349                                        outb += BLOCKW;
     350                                }
     351                                continue;
     352                        } else {
     353                                static const struct { uint16 mask; uint8 sh1, sh2; } maskTbl[6] = {
     354                                        {0xFF00, 0, 0},
     355                                        {0x0FF0, 8, 0},
     356                                        {0x00FF, 8, 8},
     357                                        {0x0F0F, 8, 4},
     358                                        {0xF0F0, 4, 0},
     359                                        {0xF00F, 4, 4}
     360                                };
     361
     362                                bool smallMask = false;
     363
     364                                // here we check if the difference bitmap can be stored in only one byte
     365                                for (int m = 0; m < 6; m++) {
     366                                        if ((diffMap & maskTbl[m].mask) == 0) {
     367                                                smallMask = true;
     368                                                *outb++ = 10 + m;
     369                                                *outb++ = ((diffMap >> maskTbl[m].sh1) & 0xF0) | ((diffMap >> maskTbl[m].sh2) & 0x0F);
     370                                                break;
     371                                        }
     372                                }
     373
     374                                if (!smallMask) {
     375                                        *outb++ = 1;
     376                                        *(unsigned short*)outb = diffMap;
     377                                        outb += 2;
     378                                }
     379
     380                                memcpy(outb, diffPix, diffCount);
     381                                outb += diffCount;
     382                                continue;
     383                        }
     384                }
     385        }
     386
     387        return outb - outbuf;
     388}
     389
    183390int read_png_file(char* filename, unsigned char *&image, unsigned char *&palette, int &width, int &height) {
    184391        png_byte header[8];
    185392