Ticket #8545: dxa.patch

File dxa.patch, 8.8 KB (added by johndoe123, 13 years ago)

Patch for encode_dxa

  • 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
    3842//#define USE_ZMBV
    3943
    4044#ifdef USE_ZMBV
     
    5660        int _codecBufSize;
    5761#endif
    5862
     63        bool m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2);
     64        bool m12blockIsSolidColor(byte *frame, int x, int y, byte &color);
     65        void m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]);
     66        bool m12motionVector(byte *frame, int x, int y, int &mx, int &my);
     67        uLong m12encode(byte *frame, byte *outbuf);
     68
    5969public:
    6070        DxaEncoder(char *filename, int width, int height, int fps);
    6171        ~DxaEncoder();
     
    144154                if (_framecount == 0)
    145155                        compType = 2;
    146156                else
    147                         compType = 3;
     157                        //compType = 3;
     158                        compType = 12;
    148159
    149160#ifdef USE_ZMBV
    150161                compType = 10;
     
    223234                                break;
    224235                        }
    225236#endif
     237                case 12:
     238
     239                        {
     240
     241                                uLong outsize1 = _width * _height;
     242                                uLong outsize2 = outsize1;
     243                                uLong outsize3 = outsize1*2;
     244                                uLong outsize4 = outsize1;
     245                                uLong outsize;
     246                                uint8 *outbuf;
     247                                uint8 *outbuf1 = new uint8[outsize1];
     248                                uint8 *outbuf2 = new uint8[outsize2];
     249                                uint8 *outbuf3 = new uint8[outsize3];
     250                                uint8 *outbuf4 = new uint8[outsize4];
     251                                uint8 *xorbuf = new uint8[_width * _height];
     252
     253                                for (int i = 0; i < _width * _height; i++)
     254                                        xorbuf[i] = _prevframe[i] ^ frame[i];
     255
     256                                compress2(outbuf1, &outsize1, xorbuf, _width * _height, 9);
     257                                compress2(outbuf2, &outsize2, frame, _width * _height, 9);
     258                                if (outsize1 < outsize2) {
     259                                        compType = 3;
     260                                        outsize = outsize1;
     261                                        outbuf = outbuf1;
     262                                } else {
     263                                        compType = 2;
     264                                        outsize = outsize2;
     265                                        outbuf = outbuf2;
     266                                }
     267
     268                                outsize3 = m12encode(frame, outbuf3);
     269
     270                                compress2(outbuf4, &outsize4, outbuf3, outsize3, 9);
     271
     272                                if (outsize4 < outsize) {
     273                                        compType = 12;
     274                                        outsize = outsize4;
     275                                        outbuf = outbuf4;
     276                                }
     277
     278                                writeByte(_dxa, compType);
     279                                writeUint32BE(_dxa, outsize);
     280                                fwrite(outbuf, outsize, 1, _dxa);
     281
     282                                delete[] outbuf1;
     283                                delete[] outbuf2;
     284                                delete[] outbuf3;
     285                                delete[] outbuf4;
     286                                delete[] xorbuf;
     287
     288                                break;
     289                        }
    226290                }
    227291
    228292                memcpy(_prevframe, frame, _width * _height);
     
    234298        _framecount++;
    235299}
    236300
     301bool DxaEncoder::m12blocksAreEqual(byte *frame, int x, int y, int x2, int y2) {
     302        byte *b1 = _prevframe + x + y * _width;
     303        byte *b2 = frame + x2 + y2 * _width;
     304        for (int yc = 0; yc < BLOCKH; yc++) {
     305                if(memcmp(b1, b2, BLOCKW))
     306                        return false;
     307                b1 += _width;
     308                b2 += _width;
     309        }
     310        return true;
     311}
     312
     313bool DxaEncoder::m12blockIsSolidColor(byte *frame, int x, int y, byte &color) {
     314        byte *b2 = frame + x + y * _width;
     315        color = *b2;
     316        for (int yc = 0; yc < BLOCKH; yc++) {
     317                for (int xc = 0; xc < BLOCKW; xc++) {
     318                        if (b2[xc] != color)
     319                                return false;
     320                }
     321                b2 += _width;
     322        }
     323        return true;
     324}
     325
     326void DxaEncoder::m12blockDelta(byte *frame, int x, int y, unsigned short &diffMap, int &diffCount, byte diffPix[]) {
     327        byte *b1 = _prevframe + x + y * _width;
     328        byte *b2 = frame + x + y * _width;
     329        diffCount = 0;
     330        diffMap = 0;
     331        for (int yc = 0; yc < BLOCKH; yc++) {
     332                for (int xc = 0; xc < BLOCKW; xc++) {
     333                        if (b1[xc] != b2[xc])
     334                        {
     335                                diffMap = (diffMap << 1) | 1;
     336                                diffPix[diffCount++] = b2[xc];
     337                        } else {
     338                                diffMap = (diffMap << 1) | 0;
     339                        }
     340                }
     341                b1 += _width;
     342                b2 += _width;
     343        }
     344}
     345
     346bool DxaEncoder::m12motionVector(byte *frame, int x, int y, int &mx, int &my) {
     347        int xmin = (0 > x-7) ? 0 : x-7;
     348        int ymin = (0 > y-7) ? 0 : y-7;
     349        int xmax = (_width < x+8) ? _width : x+8;
     350        int ymax = (_height < y+8) ? _height : y+8;
     351        for (int yc = ymin; yc < ymax; yc++) {
     352                for (int xc = xmin; xc < xmax; xc++) {
     353                        if (m12blocksAreEqual(frame, xc, yc, x, y)) {
     354                                mx = xc - x;
     355                                my = yc - y;
     356                                return true;
     357                        }
     358                }
     359        }
     360        return false;
     361}
     362
     363uLong DxaEncoder::m12encode(byte *frame, byte *outbuf) {
     364
     365        byte *outb = outbuf;
     366
     367        byte color;
     368        int mx, my;
     369        unsigned short diffMap;
     370        int diffCount;
     371        byte diffPix[BLOCKW*BLOCKH];
     372
     373        int curBlock = 0;
     374
     375        for (int by = 0; by < _height; by += BLOCKH) {
     376                for (int bx = 0; bx < _width; bx += BLOCKW) {
     377
     378                        if (m12blocksAreEqual(frame, bx, by, bx, by)) {
     379                                *outb++ = 0;
     380                                continue;
     381                        }
     382
     383                        if (m12blockIsSolidColor(frame, bx, by, color)) {
     384                                *outb++ = 2;
     385                                *outb++ = color;
     386                                continue;
     387                        }
     388
     389                        if (m12motionVector(frame, bx, by, mx, my)) {
     390                                byte mbyte = 0;
     391                                if (mx < 0) mbyte |= 0x80;
     392                                mbyte |= (abs(mx) & 7) << 4;
     393                                if (my < 0) mbyte |= 0x08;
     394                                mbyte |= abs(my) & 7;
     395                                *outb++ = 4;
     396                                *outb++ = mbyte;
     397                                continue;
     398                        }
     399
     400                        m12blockDelta(frame, bx, by, diffMap, diffCount, diffPix);
     401
     402                        if (diffCount >= 14) {
     403                                // in this case we store all 16 pixels
     404                                *outb++ = 3;
     405                                byte *b2 = (byte*)frame + bx + by * _width;
     406                                for (int yc = 0; yc < BLOCKH; yc++) {
     407                                        memcpy(outb, b2, BLOCKW);
     408                                        b2 += _width;
     409                                        outb += BLOCKW;
     410                                }
     411                                continue;
     412                        } else {
     413
     414                                static const struct { uint16 mask; uint8 sh1, sh2; } maskTbl[6] = {
     415                                        {0xFF00, 0, 0},
     416                                        {0x0FF0, 8, 0},
     417                                        {0x00FF, 8, 8},
     418                                        {0x0F0F, 8, 4},
     419                                        {0xF0F0, 4, 0},
     420                                        {0xF00F, 4, 4}
     421                                };
     422
     423                                bool smallMask = false;
     424
     425                                // here we check if the difference bitmap can be stored in only one byte
     426                                for (int m = 0; m < 6; m++) {
     427                                        if ((diffMap & maskTbl[m].mask) == 0) {
     428                                                smallMask = true;
     429                                                *outb++ = 10 + m;
     430                                                *outb++ = ((diffMap >> maskTbl[m].sh1) & 0xF0) | ((diffMap >> maskTbl[m].sh2) & 0x0F);
     431                                                break;
     432                                        }
     433                                }
     434
     435                                if (!smallMask) {
     436                                        *outb++ = 1;
     437                                        *(unsigned short*)outb = diffMap;
     438                                        outb += 2;
     439                                }
     440
     441                                memcpy(outb, diffPix, diffCount);
     442                                outb += diffCount;
     443                                continue;
     444                        }
     445
     446                }
     447        }
     448
     449        return outb - outbuf;
     450}
     451
    237452int read_png_file(char* filename, unsigned char *&image, unsigned char *&palette, int &width, int &height) {
    238453        png_byte header[8];
    239454
     
    304519                free(row_pointers[y]);
    305520        free(row_pointers);
    306521
    307         if (palette) {
     522        {
    308523                png_colorp pngpalette;
    309524                int num_palette;
    310525