ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

dxa_decoder.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/debug.h"
00024 #include "common/endian.h"
00025 #include "common/system.h"
00026 #include "common/stream.h"
00027 #include "common/textconsole.h"
00028 
00029 #include "graphics/surface.h"
00030 
00031 #include "video/dxa_decoder.h"
00032 
00033 #ifdef USE_ZLIB
00034   #include "common/zlib.h"
00035 #endif
00036 
00037 namespace Video {
00038 
00039 DXADecoder::DXADecoder() {
00040 }
00041 
00042 DXADecoder::~DXADecoder() {
00043     close();
00044 }
00045 
00046 bool DXADecoder::loadStream(Common::SeekableReadStream *stream) {
00047     close();
00048 
00049     uint32 tag = stream->readUint32BE();
00050 
00051     if (tag != MKTAG('D','E','X','A')) {
00052         close();
00053         return false;
00054     }
00055 
00056     DXAVideoTrack *track = new DXAVideoTrack(stream);
00057     addTrack(track);
00058 
00059     readSoundData(stream);
00060 
00061     track->setFrameStartPos();
00062     return true;
00063 }
00064 
00065 void DXADecoder::readSoundData(Common::SeekableReadStream *stream) {
00066     // Skip over the tag by default
00067     stream->readUint32BE();
00068 }
00069 
00070 DXADecoder::DXAVideoTrack::DXAVideoTrack(Common::SeekableReadStream *stream) {
00071     _fileStream = stream;
00072     _curFrame = -1;
00073     _frameStartOffset = 0;
00074     _decompBuffer = 0;
00075     _inBuffer = 0;
00076     memset(_palette, 0, 256 * 3);
00077 
00078     uint8 flags = _fileStream->readByte();
00079     _frameCount = _fileStream->readUint16BE();
00080     int32 frameRate = _fileStream->readSint32BE();
00081 
00082     if (frameRate > 0)
00083         _frameRate = 1000 / frameRate;
00084     else if (frameRate < 0)
00085         _frameRate = 100000 / (-frameRate);
00086     else
00087         _frameRate = 10;
00088 
00089     _width = _fileStream->readUint16BE();
00090     _height = _fileStream->readUint16BE();
00091 
00092     if (flags & 0x80) {
00093         _scaleMode = S_INTERLACED;
00094         _curHeight = _height / 2;
00095     } else if (flags & 0x40) {
00096         _scaleMode = S_DOUBLE;
00097         _curHeight = _height / 2;
00098     } else {
00099         _scaleMode = S_NONE;
00100         _curHeight = _height;
00101     }
00102 
00103     _surface = new Graphics::Surface();
00104     _surface->format = Graphics::PixelFormat::createFormatCLUT8();
00105 
00106     debug(2, "flags 0x0%x framesCount %d width %d height %d rate %d", flags, getFrameCount(), getWidth(), getHeight(), getFrameRate().toInt());
00107 
00108     _frameSize = _width * _height;
00109     _decompBufferSize = _frameSize;
00110     _frameBuffer1 = new byte[_frameSize];
00111     memset(_frameBuffer1, 0, _frameSize);
00112     _frameBuffer2 = new byte[_frameSize];
00113     memset(_frameBuffer2, 0, _frameSize);
00114 
00115     _scaledBuffer = 0;
00116     if (_scaleMode != S_NONE) {
00117         _scaledBuffer = new byte[_frameSize];
00118         memset(_scaledBuffer, 0, _frameSize);
00119     }
00120 
00121 #ifdef DXA_EXPERIMENT_MAXD
00122     // Check for an extended header
00123     if (flags & 1) {
00124         uint32 size;
00125 
00126         do {
00127             tag = _fileStream->readUint32BE();
00128 
00129             if (tag != 0)
00130                 size = _fileStream->readUint32BE();
00131 
00132             switch (tag) {
00133                 case 0: // No more tags
00134                     break;
00135                 case MKTAG('M','A','X','D'):
00136                     assert(size == 4);
00137                     _decompBufferSize = _fileStream->readUint32BE();
00138                     break;
00139                 default: // Unknown tag - skip it.
00140                     while (size > 0) {
00141                         byte dummy = _fileStream->readByte();
00142                         size--;
00143                     }
00144                     break;
00145             }
00146         } while (tag != 0);
00147     }
00148 #endif
00149 }
00150 
00151 DXADecoder::DXAVideoTrack::~DXAVideoTrack() {
00152     delete _fileStream;
00153     delete _surface;
00154     delete[] _frameBuffer1;
00155     delete[] _frameBuffer2;
00156     delete[] _scaledBuffer;
00157     delete[] _inBuffer;
00158     delete[] _decompBuffer;
00159 }
00160 
00161 bool DXADecoder::DXAVideoTrack::rewind() {
00162     _curFrame = -1;
00163     _fileStream->seek(_frameStartOffset);
00164     return true;
00165 }
00166 
00167 Graphics::PixelFormat DXADecoder::DXAVideoTrack::getPixelFormat() const {
00168     return _surface->format;
00169 }
00170 
00171 void DXADecoder::DXAVideoTrack::setFrameStartPos() {
00172     _frameStartOffset = _fileStream->pos();
00173 }
00174 
00175 void DXADecoder::DXAVideoTrack::decodeZlib(byte *data, int size, int totalSize) {
00176 #ifdef USE_ZLIB
00177     unsigned long dstLen = totalSize;
00178     Common::uncompress(data, &dstLen, _inBuffer, size);
00179 #endif
00180 }
00181 
00182 #define BLOCKW 4
00183 #define BLOCKH 4
00184 
00185 void DXADecoder::DXAVideoTrack::decode12(int size) {
00186 #ifdef USE_ZLIB
00187     if (!_decompBuffer) {
00188         _decompBuffer = new byte[_decompBufferSize];
00189         memset(_decompBuffer, 0, _decompBufferSize);
00190     }
00191 
00192     /* decompress the input data */
00193     decodeZlib(_decompBuffer, size, _decompBufferSize);
00194 
00195     byte *dat = _decompBuffer;
00196 
00197     memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
00198 
00199     for (uint32 by = 0; by < _height; by += BLOCKH) {
00200         for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
00201             byte type = *dat++;
00202             byte *b2 = _frameBuffer1 + bx + by * _width;
00203 
00204             switch (type) {
00205             case 0:
00206                 break;
00207             case 10:
00208             case 11:
00209             case 12:
00210             case 13:
00211             case 14:
00212             case 15:
00213             case 1: {
00214                 unsigned short diffMap;
00215                 if (type >= 10 && type <= 15) {
00216                     static const struct { uint8 sh1, sh2; } shiftTbl[6] = {
00217                         {0, 0}, {8, 0}, {8, 8}, {8, 4}, {4, 0}, {4, 4}
00218                     };
00219                     diffMap = ((*dat & 0xF0) << shiftTbl[type-10].sh1) |
00220                           ((*dat & 0x0F) << shiftTbl[type-10].sh2);
00221                     dat++;
00222                 } else {
00223                     diffMap = *(unsigned short*)dat;
00224                     dat += 2;
00225                 }
00226 
00227                 for (int yc = 0; yc < BLOCKH; yc++) {
00228                     for (int xc = 0; xc < BLOCKW; xc++) {
00229                         if (diffMap & 0x8000) {
00230                             b2[xc] = *dat++;
00231                         }
00232                         diffMap <<= 1;
00233                     }
00234                     b2 += _width;
00235                 }
00236                 break;
00237             }
00238             case 2: {
00239                 byte color = *dat++;
00240 
00241                 for (int yc = 0; yc < BLOCKH; yc++) {
00242                     for (int xc = 0; xc < BLOCKW; xc++) {
00243                         b2[xc] = color;
00244                     }
00245                     b2 += _width;
00246                 }
00247                 break;
00248             }
00249             case 3: {
00250                 for (int yc = 0; yc < BLOCKH; yc++) {
00251                     for (int xc = 0; xc < BLOCKW; xc++) {
00252                         b2[xc] = *dat++;
00253                     }
00254                     b2 += _width;
00255                 }
00256                 break;
00257             }
00258             case 4: {
00259                 byte mbyte = *dat++;
00260                 int mx = (mbyte >> 4) & 0x07;
00261                 if (mbyte & 0x80)
00262                     mx = -mx;
00263                 int my = mbyte & 0x07;
00264                 if (mbyte & 0x08)
00265                     my = -my;
00266                 byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _width;
00267                 for (int yc = 0; yc < BLOCKH; yc++) {
00268                     memcpy(b2, b1, BLOCKW);
00269                     b1 += _width;
00270                     b2 += _width;
00271                 }
00272                 break;
00273             }
00274             case 5:
00275                 break;
00276             default:
00277                 error("decode12: Unknown type %d", type);
00278             }
00279         }
00280     }
00281 #endif
00282 }
00283 
00284 void DXADecoder::DXAVideoTrack::decode13(int size) {
00285 #ifdef USE_ZLIB
00286     uint8 *codeBuf, *dataBuf, *motBuf, *maskBuf;
00287 
00288     if (!_decompBuffer) {
00289         _decompBuffer = new byte[_decompBufferSize];
00290         memset(_decompBuffer, 0, _decompBufferSize);
00291     }
00292 
00293     /* decompress the input data */
00294     decodeZlib(_decompBuffer, size, _decompBufferSize);
00295 
00296     memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
00297 
00298     int codeSize = _width * _curHeight / 16;
00299     int dataSize, motSize;
00300 
00301     dataSize = READ_BE_UINT32(&_decompBuffer[0]);
00302     motSize  = READ_BE_UINT32(&_decompBuffer[4]);
00303     //maskSize = READ_BE_UINT32(&_decompBuffer[8]);
00304 
00305     codeBuf = &_decompBuffer[12];
00306     dataBuf = &codeBuf[codeSize];
00307     motBuf = &dataBuf[dataSize];
00308     maskBuf = &motBuf[motSize];
00309 
00310     for (uint32 by = 0; by < _curHeight; by += BLOCKH) {
00311         for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
00312             uint8 type = *codeBuf++;
00313             uint8 *b2 = (uint8 *)_frameBuffer1 + bx + by * _width;
00314 
00315             switch (type) {
00316             case 0:
00317                 break;
00318 
00319             case 1: {
00320                 uint16 diffMap = READ_BE_UINT16(maskBuf);
00321                 maskBuf += 2;
00322 
00323                 for (int yc = 0; yc < BLOCKH; yc++) {
00324                     for (int xc = 0; xc < BLOCKW; xc++) {
00325                         if (diffMap & 0x8000) {
00326                             b2[xc] = *dataBuf++;
00327                         }
00328                         diffMap <<= 1;
00329                     }
00330                     b2 += _width;
00331                 }
00332                 break;
00333             }
00334             case 2: {
00335                 uint8 color = *dataBuf++;
00336 
00337                 for (int yc = 0; yc < BLOCKH; yc++) {
00338                     for (int xc = 0; xc < BLOCKW; xc++) {
00339                         b2[xc] = color;
00340                     }
00341                     b2 += _width;
00342                 }
00343                 break;
00344             }
00345             case 3: {
00346                 for (int yc = 0; yc < BLOCKH; yc++) {
00347                     for (int xc = 0; xc < BLOCKW; xc++) {
00348                         b2[xc] = *dataBuf++;
00349                     }
00350                     b2 += _width;
00351                 }
00352                 break;
00353             }
00354             case 4: {
00355                 uint8 mbyte = *motBuf++;
00356 
00357                 int mx = (mbyte >> 4) & 0x07;
00358                 if (mbyte & 0x80)
00359                     mx = -mx;
00360                 int my = mbyte & 0x07;
00361                 if (mbyte & 0x08)
00362                     my = -my;
00363 
00364                 uint8 *b1 = (uint8 *)_frameBuffer2 + (bx+mx) + (by+my) * _width;
00365                 for (int yc = 0; yc < BLOCKH; yc++) {
00366                     memcpy(b2, b1, BLOCKW);
00367                     b1 += _width;
00368                     b2 += _width;
00369                 }
00370                 break;
00371             }
00372             case 8: {
00373                 static const int subX[4] = {0, 2, 0, 2};
00374                 static const int subY[4] = {0, 0, 2, 2};
00375 
00376                 uint8 subMask = *maskBuf++;
00377 
00378                 for (int subBlock = 0; subBlock < 4; subBlock++) {
00379                     int sx = bx + subX[subBlock], sy = by + subY[subBlock];
00380                     b2 = (uint8 *)_frameBuffer1 + sx + sy * _width;
00381                     switch (subMask & 0xC0) {
00382                     // 00: skip
00383                     case 0x00:
00384                         break;
00385                     // 01: solid color
00386                     case 0x40: {
00387                         uint8 subColor = *dataBuf++;
00388                         for (int yc = 0; yc < BLOCKH / 2; yc++) {
00389                             for (int xc = 0; xc < BLOCKW / 2; xc++) {
00390                                 b2[xc] = subColor;
00391                             }
00392                             b2 += _width;
00393                         }
00394                         break;
00395                     }
00396                     // 02: motion vector
00397                     case 0x80: {
00398                         uint8 mbyte = *motBuf++;
00399 
00400                         int mx = (mbyte >> 4) & 0x07;
00401                         if (mbyte & 0x80)
00402                             mx = -mx;
00403 
00404                         int my = mbyte & 0x07;
00405                         if (mbyte & 0x08)
00406                             my = -my;
00407 
00408                         uint8 *b1 = (uint8 *)_frameBuffer2 + (sx+mx) + (sy+my) * _width;
00409                         for (int yc = 0; yc < BLOCKH / 2; yc++) {
00410                             memcpy(b2, b1, BLOCKW / 2);
00411                             b1 += _width;
00412                             b2 += _width;
00413                         }
00414                         break;
00415                     }
00416                     // 03: raw
00417                     case 0xC0:
00418                         for (int yc = 0; yc < BLOCKH / 2; yc++) {
00419                             for (int xc = 0; xc < BLOCKW / 2; xc++) {
00420                                 b2[xc] = *dataBuf++;
00421                             }
00422                             b2 += _width;
00423                         }
00424                         break;
00425                     }
00426                     subMask <<= 2;
00427                 }
00428                 break;
00429             }
00430             case 32:
00431             case 33:
00432             case 34: {
00433                 int count = type - 30;
00434                 uint8 pixels[4];
00435 
00436                 memcpy(pixels, dataBuf, count);
00437                 dataBuf += count;
00438 
00439                 if (count == 2) {
00440                     uint16 code = READ_BE_UINT16(maskBuf);
00441                     maskBuf += 2;
00442                     for (int yc = 0; yc < BLOCKH; yc++) {
00443                         for (int xc = 0; xc < BLOCKW; xc++) {
00444                             b2[xc] = pixels[code & 1];
00445                             code >>= 1;
00446                         }
00447                         b2 += _width;
00448                     }
00449                 } else {
00450                     uint32 code = READ_BE_UINT32(maskBuf);
00451                     maskBuf += 4;
00452                     for (int yc = 0; yc < BLOCKH; yc++) {
00453                         for (int xc = 0; xc < BLOCKW; xc++) {
00454                             b2[xc] = pixels[code & 3];
00455                             code >>= 2;
00456                         }
00457                         b2 += _width;
00458                     }
00459                 }
00460                 break;
00461             }
00462             default:
00463                 error("decode13: Unknown type %d", type);
00464             }
00465         }
00466     }
00467 #endif
00468 }
00469 
00470 const Graphics::Surface *DXADecoder::DXAVideoTrack::decodeNextFrame() {
00471     uint32 tag = _fileStream->readUint32BE();
00472     if (tag == MKTAG('C','M','A','P')) {
00473         _fileStream->read(_palette, 256 * 3);
00474         _dirtyPalette = true;
00475     }
00476 
00477     tag = _fileStream->readUint32BE();
00478     if (tag == MKTAG('F','R','A','M')) {
00479         byte type = _fileStream->readByte();
00480         uint32 size = _fileStream->readUint32BE();
00481 
00482         if (!_inBuffer || _inBufferSize < size) {
00483             delete[] _inBuffer;
00484             _inBuffer = new byte[size];
00485             memset(_inBuffer, 0, size);
00486             _inBufferSize = size;
00487         }
00488 
00489         _fileStream->read(_inBuffer, size);
00490 
00491         switch (type) {
00492         case 2:
00493             decodeZlib(_frameBuffer1, size, _frameSize);
00494             break;
00495         case 3:
00496             decodeZlib(_frameBuffer2, size, _frameSize);
00497             break;
00498         case 12:
00499             decode12(size);
00500             break;
00501         case 13:
00502             decode13(size);
00503             break;
00504         default:
00505             error("decodeFrame: Unknown compression type %d", type);
00506         }
00507 
00508         if (type == 3) {
00509             for (uint32 j = 0; j < _curHeight; ++j) {
00510                 for (uint32 i = 0; i < _width; ++i) {
00511                     const int offs = j * _width + i;
00512                     _frameBuffer1[offs] ^= _frameBuffer2[offs];
00513                 }
00514             }
00515         }
00516     }
00517 
00518     switch (_scaleMode) {
00519     case S_INTERLACED:
00520         for (int cy = 0; cy < _curHeight; cy++) {
00521             memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
00522             memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width);
00523         }
00524         _surface->setPixels(_scaledBuffer);
00525         break;
00526     case S_DOUBLE:
00527         for (int cy = 0; cy < _curHeight; cy++) {
00528             memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
00529             memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width);
00530         }
00531         _surface->setPixels(_scaledBuffer);
00532         break;
00533     case S_NONE:
00534         _surface->setPixels(_frameBuffer1);
00535         break;
00536     }
00537 
00538     // Copy in the relevant info to the Surface
00539     _surface->w = getWidth();
00540     _surface->h = getHeight();
00541     _surface->pitch = getWidth();
00542 
00543     _curFrame++;
00544 
00545     return _surface;
00546 }
00547 
00548 } // End of namespace Video


Generated on Sat Nov 30 2019 05:00:34 for ResidualVM by doxygen 1.7.1
curved edge   curved edge