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

svq1.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 // Sorenson Video 1 Codec
00024 // Based off FFmpeg's SVQ1 decoder (written by Arpi and Nick Kurshev)
00025 
00026 #include "image/codecs/svq1.h"
00027 #include "image/codecs/svq1_cb.h"
00028 #include "image/codecs/svq1_vlc.h"
00029 
00030 #include "common/stream.h"
00031 #include "common/bitstream.h"
00032 #include "common/rect.h"
00033 #include "common/system.h"
00034 #include "common/debug.h"
00035 #include "common/textconsole.h"
00036 #include "common/huffman.h"
00037 
00038 #include "graphics/yuv_to_rgb.h"
00039 
00040 namespace Image {
00041 
00042 #define SVQ1_BLOCK_SKIP     0
00043 #define SVQ1_BLOCK_INTER    1
00044 #define SVQ1_BLOCK_INTER_4V 2
00045 #define SVQ1_BLOCK_INTRA    3
00046 
00047 SVQ1Decoder::SVQ1Decoder(uint16 width, uint16 height) {
00048     debug(1, "SVQ1Decoder::SVQ1Decoder(width:%d, height:%d)", width, height);
00049     _width = width;
00050     _height = height;
00051     _frameWidth = _frameHeight = 0;
00052     _surface = 0;
00053 
00054     _last[0] = 0;
00055     _last[1] = 0;
00056     _last[2] = 0;
00057 
00058     // Setup Variable Length Code Tables
00059     _blockType = new HuffmanDecoder(0, 4, s_svq1BlockTypeCodes, s_svq1BlockTypeLengths);
00060 
00061     for (int i = 0; i < 6; i++) {
00062         _intraMultistage[i] = new HuffmanDecoder(0, 8, s_svq1IntraMultistageCodes[i], s_svq1IntraMultistageLengths[i]);
00063         _interMultistage[i] = new HuffmanDecoder(0, 8, s_svq1InterMultistageCodes[i], s_svq1InterMultistageLengths[i]);
00064     }
00065 
00066     _intraMean = new HuffmanDecoder(0, 256, s_svq1IntraMeanCodes, s_svq1IntraMeanLengths);
00067     _interMean = new HuffmanDecoder(0, 512, s_svq1InterMeanCodes, s_svq1InterMeanLengths);
00068     _motionComponent = new HuffmanDecoder(0, 33, s_svq1MotionComponentCodes, s_svq1MotionComponentLengths);
00069 }
00070 
00071 SVQ1Decoder::~SVQ1Decoder() {
00072     if (_surface) {
00073         _surface->free();
00074         delete _surface;
00075     }
00076 
00077     delete[] _last[0];
00078     delete[] _last[1];
00079     delete[] _last[2];
00080 
00081     delete _blockType;
00082     delete _intraMean;
00083     delete _interMean;
00084     delete _motionComponent;
00085 
00086     for (int i = 0; i < 6; i++) {
00087         delete _intraMultistage[i];
00088         delete _interMultistage[i];
00089     }
00090 }
00091 
00092 #define ALIGN(x, a) (((x)+(a)-1)&~((a)-1))
00093 
00094 const Graphics::Surface *SVQ1Decoder::decodeFrame(Common::SeekableReadStream &stream) {
00095     debug(1, "SVQ1Decoder::decodeImage()");
00096 
00097     Common::BitStream32BEMSB frameData(stream);
00098 
00099     uint32 frameCode = frameData.getBits(22);
00100     debug(1, " frameCode: %d", frameCode);
00101 
00102     if ((frameCode & ~0x70) || !(frameCode & 0x60)) { // Invalid
00103         warning("Invalid Image at frameCode");
00104         return _surface;
00105     }
00106 
00107     byte temporalReference = frameData.getBits(8);
00108     debug(1, " temporalReference: %d", temporalReference);
00109     static const char *const types[4] = { "I (Key)", "P (Delta from Previous)", "B (Delta from Next)", "Invalid" };
00110     byte frameType = frameData.getBits(2);
00111     debug(1, " frameType: %d = %s Frame", frameType, types[frameType]);
00112 
00113     if (frameType == 0) { // I Frame
00114         // TODO: Validate checksum if present
00115         if (frameCode == 0x50 || frameCode == 0x60) {
00116             uint32 checksum = frameData.getBits(16);
00117             debug(1, " checksum:0x%02x", checksum);
00118             // We're currently just ignoring the checksum
00119         }
00120 
00121         if ((frameCode ^ 0x10) >= 0x50) {
00122             // Skip embedded string
00123             byte stringLen = frameData.getBits(8);
00124             for (uint16 i = 0; i < stringLen-1; i++)
00125                 frameData.skip(8);
00126         }
00127 
00128         frameData.skip(5); // Unknown
00129 
00130         static const struct { uint w, h; } standardFrameSizes[7] = {
00131             { 160, 120 }, // 0
00132             { 128,  96 }, // 1
00133             { 176, 144 }, // 2
00134             { 352, 288 }, // 3
00135             { 704, 576 }, // 4
00136             { 240, 180 }, // 5
00137             { 320, 240 }  // 6
00138         };
00139 
00140         byte frameSizeCode = frameData.getBits(3);
00141         debug(1, " frameSizeCode: %d", frameSizeCode);
00142 
00143         if (frameSizeCode == 7) {
00144             _frameWidth = frameData.getBits(12);
00145             _frameHeight = frameData.getBits(12);
00146         } else {
00147             _frameWidth = standardFrameSizes[frameSizeCode].w;
00148             _frameHeight = standardFrameSizes[frameSizeCode].h;
00149         }
00150 
00151         debug(1, " frameWidth: %d", _frameWidth);
00152         debug(1, " frameHeight: %d", _frameHeight);
00153     } else if (frameType == 2) { // B Frame
00154         warning("B Frames not supported by SVQ1 decoder (yet)");
00155         return _surface;
00156     } else if (frameType == 3) { // Invalid
00157         warning("Invalid Frame Type");
00158         return _surface;
00159     }
00160 
00161     bool checksumPresent = frameData.getBit() != 0;
00162     debug(1, " checksumPresent: %d", checksumPresent);
00163     if (checksumPresent) {
00164         bool usePacketChecksum = frameData.getBit() != 0;
00165         debug(1, " usePacketChecksum: %d", usePacketChecksum);
00166         bool componentChecksumsAfterImageData = frameData.getBit() != 0;
00167         debug(1, " componentChecksumsAfterImageData: %d", componentChecksumsAfterImageData);
00168         byte unk4 = frameData.getBits(2);
00169         debug(1, " unk4: %d", unk4);
00170         if (unk4 != 0)
00171             warning("Invalid Frame Header in SVQ1 Frame Decode");
00172     }
00173 
00174     // Some more unknown data
00175     bool unk5 = frameData.getBit() != 0;
00176     if (unk5) {
00177         frameData.skip(8);
00178 
00179         while (frameData.getBit() != 0)
00180             frameData.skip(8);
00181     }
00182 
00183     uint yWidth = ALIGN(_frameWidth, 16);
00184     uint yHeight = ALIGN(_frameHeight, 16);
00185     uint uvWidth = ALIGN(yWidth / 4, 16);
00186     uint uvHeight = ALIGN(yHeight / 4, 16);
00187     uint uvPitch = uvWidth + 4; // we need at least one extra column and pitch must be divisible by 4
00188 
00189     byte *current[3];
00190 
00191     // Decode Y, U and V component planes
00192     for (int i = 0; i < 3; i++) {
00193         uint width, height, pitch;
00194         if (i == 0) {
00195             width = yWidth;
00196             height = yHeight;
00197             pitch = width;
00198             current[i] = new byte[width * height];
00199         } else {
00200             width = uvWidth;
00201             height = uvHeight;
00202             pitch = uvPitch;
00203 
00204             // Add an extra row here. See below for more information.
00205             current[i] = new byte[pitch * (height + 1)];
00206         }
00207 
00208         if (frameType == 0) { // I Frame
00209             // Keyframe (I)
00210             byte *currentP = current[i];
00211             for (uint16 y = 0; y < height; y += 16) {
00212                 for (uint16 x = 0; x < width; x += 16) {
00213                     if (!svq1DecodeBlockIntra(&frameData, &currentP[x], pitch)) {
00214                         warning("svq1DecodeBlockIntra decode failure");
00215                         return _surface;
00216                     }
00217                 }
00218                 currentP += 16 * pitch;
00219             }
00220         } else {
00221             // Delta frame (P or B)
00222 
00223             // Prediction Motion Vector
00224             Common::Point *pmv = new Common::Point[(width / 8) + 3];
00225 
00226             byte *previous = 0;
00227             if (frameType == 2) { // B Frame
00228                 error("SVQ1 Video: B Frames not supported");
00229                 //previous = _next[i];
00230             } else {
00231                 previous = _last[i];
00232             }
00233 
00234             byte *currentP = current[i];
00235             for (uint16 y = 0; y < height; y += 16) {
00236                 for (uint16 x = 0; x < width; x += 16) {
00237                     if (!svq1DecodeDeltaBlock(&frameData, &currentP[x], previous, pitch, pmv, x, y)) {
00238                         warning("svq1DecodeDeltaBlock decode failure");
00239                         return _surface;
00240                     }
00241                 }
00242 
00243                 pmv[0].x = pmv[0].y = 0;
00244 
00245                 currentP += 16 * pitch;
00246             }
00247 
00248             delete[] pmv;
00249         }
00250     }
00251 
00252     // Now we'll create the surface
00253     if (!_surface) {
00254         _surface = new Graphics::Surface();
00255         _surface->create(yWidth, yHeight, g_system->getScreenFormat());
00256         _surface->w = _width;
00257         _surface->h = _height;
00258     }
00259 
00260     // We need to massage the chrominance data a bit to be able to be used by the converter
00261     // Since the thing peeks at values one column and one row beyond the data, we need to fill it in
00262 
00263     // First, fill in the column-after-last with the last column's value
00264     for (uint i = 0; i < uvHeight; i++) {
00265         current[1][i * uvPitch + uvWidth] = current[1][i * uvPitch + uvWidth - 1];
00266         current[2][i * uvPitch + uvWidth] = current[2][i * uvPitch + uvWidth - 1];
00267     }
00268 
00269     // Then, copy the last row to the one after the last row
00270     memcpy(current[1] + uvHeight * uvPitch, current[1] + (uvHeight - 1) * uvPitch, uvWidth + 1);
00271     memcpy(current[2] + uvHeight * uvPitch, current[2] + (uvHeight - 1) * uvPitch, uvWidth + 1);
00272 
00273     // Finally, actually do the conversion ;)
00274     YUVToRGBMan.convert410(_surface, Graphics::YUVToRGBManager::kScaleFull, current[0], current[1], current[2], yWidth, yHeight, yWidth, uvPitch);
00275 
00276     // Store the current surfaces for later and free the old ones
00277     for (int i = 0; i < 3; i++) {
00278         delete[] _last[i];
00279         _last[i] = current[i];
00280     }
00281 
00282     return _surface;
00283 }
00284 
00285 bool SVQ1Decoder::svq1DecodeBlockIntra(Common::BitStream32BEMSB *s, byte *pixels, int pitch) {
00286     // initialize list for breadth first processing of vectors
00287     byte *list[63];
00288     list[0] = pixels;
00289 
00290     // recursively process vector
00291     for (int i = 0, m = 1, n = 1, level = 5; i < n; i++) {
00292         for (; level > 0; i++) {
00293             // process next depth
00294             if (i == m) {
00295                 m = n;
00296                 if (--level == 0)
00297                     break;
00298             }
00299 
00300             // divide block if next bit set
00301             if (s->getBit() == 0)
00302                 break;
00303 
00304             // add child nodes
00305             list[n++] = list[i];
00306             list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1));
00307         }
00308 
00309         // destination address and vector size
00310         uint32 *dst = (uint32 *)list[i];
00311         uint width = 1 << ((level + 4) / 2);
00312         uint height = 1 << ((level + 3) / 2);
00313 
00314         // get number of stages (-1 skips vector, 0 for mean only)
00315         int stages = _intraMultistage[level]->getSymbol(*s) - 1;
00316 
00317         if (stages == -1) {
00318             for (uint y = 0; y < height; y++)
00319                 memset(&dst[y * (pitch / 4)], 0, width);
00320 
00321             continue; // skip vector
00322         }
00323 
00324         if (stages > 0 && level >= 4) {
00325             warning("Error (svq1_decode_block_intra): invalid vector: stages = %d, level = %d", stages, level);
00326             return false; // error - invalid vector
00327         }
00328 
00329         int mean = _intraMean->getSymbol(*s);
00330 
00331         if (stages == 0) {
00332             for (uint y = 0; y < height; y++)
00333                 memset(&dst[y * (pitch / 4)], mean, width);
00334         } else {
00335             const uint32 *codebook = (const uint32 *)s_svq1IntraCodebooks[level];
00336             uint32 bitCache = s->getBits(stages * 4);
00337 
00338             // calculate codebook entries for this vector
00339             int entries[6];
00340             for (int j = 0; j < stages; j++)
00341                 entries[j] = (((bitCache >> ((stages - j - 1) * 4)) & 0xF) + j * 16) << (level + 1);
00342 
00343             mean -= stages * 128;
00344             uint32 n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF);
00345 
00346             for (uint y = 0; y < height; y++) {
00347                 for (uint x = 0; x < (width / 4); x++, codebook++) {
00348                     uint32 n1 = n4;
00349                     uint32 n2 = n4;
00350                     uint32 n3;
00351 
00352                     // add codebook entries to vector
00353                     for (int j = 0; j < stages; j++) {
00354                         n3 = READ_UINT32(&codebook[entries[j]]) ^ 0x80808080;
00355                         n1 += (n3 & 0xFF00FF00) >> 8;
00356                         n2 += n3 & 0x00FF00FF;
00357                     }
00358 
00359                     // clip to [0..255]
00360                     if (n1 & 0xFF00FF00) {
00361                         n3 = (((n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00362                         n1 += 0x7F007F00;
00363                         n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00364                         n1 &= n3 & 0x00FF00FF;
00365                     }
00366 
00367                     if (n2 & 0xFF00FF00) {
00368                         n3 = (((n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00369                         n2 += 0x7F007F00;
00370                         n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00371                         n2 &= n3 & 0x00FF00FF;
00372                     }
00373 
00374                     // store result
00375                     dst[x] = (n1 << 8) | n2;
00376                 }
00377 
00378                 dst += pitch / 4;
00379             }
00380         }
00381     }
00382 
00383     return true;
00384 }
00385 
00386 bool SVQ1Decoder::svq1DecodeBlockNonIntra(Common::BitStream32BEMSB *s, byte *pixels, int pitch) {
00387     // initialize list for breadth first processing of vectors
00388     byte *list[63];
00389     list[0] = pixels;
00390 
00391     // recursively process vector
00392     for (int i = 0, m = 1, n = 1, level = 5; i < n; i++) {
00393         for (; level > 0; i++) {
00394             // process next depth
00395             if (i == m) {
00396                 m = n;
00397                 if (--level == 0)
00398                     break;
00399             }
00400 
00401             // divide block if next bit set
00402             if (s->getBit() == 0)
00403                 break;
00404 
00405             // add child nodes
00406             list[n++] = list[i];
00407             list[n++] = list[i] + (((level & 1) ? pitch : 1) << ((level / 2) + 1));
00408         }
00409 
00410         // destination address and vector size
00411         uint32 *dst = (uint32 *)list[i];
00412         int width = 1 << ((level + 4) / 2);
00413         int height = 1 << ((level + 3) /  2);
00414 
00415         // get number of stages (-1 skips vector, 0 for mean only)
00416         int stages = _interMultistage[level]->getSymbol(*s) - 1;
00417 
00418         if (stages == -1)
00419             continue; // skip vector
00420 
00421         if (stages > 0 && level >= 4) {
00422             warning("Error (svq1_decode_block_non_intra): invalid vector: stages = %d, level = %d", stages, level);
00423             return false; // error - invalid vector
00424         }
00425 
00426         int mean = _interMean->getSymbol(*s) - 256;
00427         const uint32 *codebook = (const uint32 *)s_svq1InterCodebooks[level];
00428         uint32 bitCache = s->getBits(stages * 4);
00429 
00430         // calculate codebook entries for this vector
00431         int entries[6];
00432         for (int j = 0; j < stages; j++)
00433             entries[j] = (((bitCache >> ((stages - j - 1) * 4)) & 0xF) + j * 16) << (level + 1);
00434 
00435         mean -= stages * 128;
00436         uint32 n4 = ((mean + (mean >> 31)) << 16) | (mean & 0xFFFF);
00437 
00438         for (int y = 0; y < height; y++) {
00439             for (int x = 0; x < (width / 4); x++, codebook++) {
00440                 uint32 n3 = dst[x];
00441 
00442                 // add mean value to vector
00443                 uint32 n1 = ((n3 & 0xFF00FF00) >> 8) + n4;
00444                 uint32 n2 = (n3 & 0x00FF00FF) + n4;
00445 
00446                 // add codebook entries to vector
00447                 for (int j = 0; j < stages; j++) {
00448                     n3 = READ_UINT32(&codebook[entries[j]]) ^ 0x80808080;
00449                     n1 += (n3 & 0xFF00FF00) >> 8;
00450                     n2 += n3 & 0x00FF00FF;
00451                 }
00452 
00453                 // clip to [0..255]
00454                 if (n1 & 0xFF00FF00) {
00455                     n3 = ((( n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00456                     n1 += 0x7F007F00;
00457                     n1 |= (((~n1 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00458                     n1 &= n3 & 0x00FF00FF;
00459                 }
00460 
00461                 if (n2 & 0xFF00FF00) {
00462                     n3  = ((( n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00463                     n2 += 0x7F007F00;
00464                     n2 |= (((~n2 >> 15) & 0x00010001) | 0x01000100) - 0x00010001;
00465                     n2 &= n3 & 0x00FF00FF;
00466                 }
00467 
00468                 // store result
00469                 dst[x] = (n1 << 8) | n2;
00470             }
00471 
00472             dst += pitch / 4;
00473         }
00474     }
00475 
00476     return true;
00477 }
00478 
00479 // median of 3
00480 static inline int midPred(int a, int b, int c) {
00481     if (a > b) {
00482         if (c > b) {
00483             if (c > a)
00484                 b = a;
00485             else
00486                 b = c;
00487         }
00488     } else {
00489         if (b > c) {
00490             if (c > a)
00491                 b = c;
00492             else
00493                 b = a;
00494         }
00495     }
00496 
00497     return b;
00498 }
00499 
00500 bool SVQ1Decoder::svq1DecodeMotionVector(Common::BitStream32BEMSB *s, Common::Point *mv, Common::Point **pmv) {
00501     for (int i = 0; i < 2; i++) {
00502         // get motion code
00503         int diff = _motionComponent->getSymbol(*s);
00504         if (diff < 0)
00505             return false; // error - invalid motion code
00506         else if (diff && s->getBit() != 0)
00507             diff = -diff;
00508 
00509         // add median of motion vector predictors and clip result
00510         if (i == 1)
00511             mv->y = ((diff + midPred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26;
00512         else
00513             mv->x = ((diff + midPred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26;
00514     }
00515 
00516     return true;
00517 }
00518 
00519 void SVQ1Decoder::svq1SkipBlock(byte *current, byte *previous, int pitch, int x, int y) {
00520     const byte *src = &previous[x + y * pitch];
00521     byte *dst = current;
00522 
00523     for (int i = 0; i < 16; i++) {
00524         memcpy(dst, src, 16);
00525         src += pitch;
00526         dst += pitch;
00527     }
00528 }
00529 
00530 void SVQ1Decoder::putPixels8C(byte *block, const byte *pixels, int lineSize, int h) {
00531     for (int i = 0; i < h; i++) {
00532         *((uint32 *)block) = READ_UINT32(pixels);
00533         *((uint32 *)(block + 4)) = READ_UINT32(pixels + 4);
00534         pixels += lineSize;
00535         block += lineSize;
00536     }
00537 }
00538 
00539 static inline uint32 rndAvg32(uint32 a, uint32 b) {
00540     return (a | b) - (((a ^ b) & ~0x01010101) >> 1);
00541 }
00542 
00543 void SVQ1Decoder::putPixels8L2(byte *dst, const byte *src1, const byte *src2,
00544         int dstStride, int srcStride1, int srcStride2, int h) {
00545     for (int i = 0; i < h; i++) {
00546         uint32 a = READ_UINT32(&src1[srcStride1 * i]);
00547         uint32 b = READ_UINT32(&src2[srcStride2 * i]);
00548         *((uint32 *)&dst[dstStride * i]) = rndAvg32(a, b);
00549         a = READ_UINT32(&src1[srcStride1 * i + 4]);
00550         b = READ_UINT32(&src2[srcStride2 * i + 4]);
00551         *((uint32 *)&dst[dstStride * i + 4]) = rndAvg32(a, b);
00552     }
00553 }
00554 
00555 void SVQ1Decoder::putPixels8X2C(byte *block, const byte *pixels, int lineSize, int h) {
00556     putPixels8L2(block, pixels, pixels + 1, lineSize, lineSize, lineSize, h);
00557 }
00558 
00559 void SVQ1Decoder::putPixels8Y2C(byte *block, const byte *pixels, int lineSize, int h) {
00560     putPixels8L2(block, pixels, pixels + lineSize, lineSize, lineSize, lineSize, h);
00561 }
00562 
00563 void SVQ1Decoder::putPixels8XY2C(byte *block, const byte *pixels, int lineSize, int h) {
00564     for (int j = 0; j < 2; j++) {
00565         uint32 a = READ_UINT32(pixels);
00566         uint32 b = READ_UINT32(pixels + 1);
00567         uint32 l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
00568         uint32 h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
00569 
00570         pixels += lineSize;
00571 
00572         for (int i = 0; i < h; i += 2) {
00573             a = READ_UINT32(pixels);
00574             b = READ_UINT32(pixels + 1);
00575             uint32 l1 = (a & 0x03030303UL) + (b & 0x03030303UL);
00576             uint32 h1 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
00577             *((uint32 *)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
00578             pixels += lineSize;
00579             block += lineSize;
00580             a = READ_UINT32(pixels);
00581             b = READ_UINT32(pixels + 1);
00582             l0 = (a & 0x03030303UL) + (b & 0x03030303UL) + 0x02020202UL;
00583             h0 = ((a & 0xFCFCFCFCUL) >> 2) + ((b & 0xFCFCFCFCUL) >> 2);
00584             *((uint32 *)block) = h0 + h1 + (((l0 + l1) >> 2) & 0x0F0F0F0FUL);
00585             pixels += lineSize;
00586             block += lineSize;
00587         }
00588 
00589         pixels += 4 - lineSize * (h + 1);
00590         block += 4 - lineSize * h;
00591     }
00592 }
00593 
00594 void SVQ1Decoder::putPixels16C(byte *block, const byte *pixels, int lineSize, int h) {
00595     putPixels8C(block, pixels, lineSize, h);
00596     putPixels8C(block + 8, pixels + 8, lineSize, h);
00597 }
00598 
00599 void SVQ1Decoder::putPixels16X2C(byte *block, const byte *pixels, int lineSize, int h) {
00600     putPixels8X2C(block, pixels, lineSize, h);
00601     putPixels8X2C(block + 8, pixels + 8, lineSize, h);
00602 }
00603 
00604 void SVQ1Decoder::putPixels16Y2C(byte *block, const byte *pixels, int lineSize, int h) {
00605     putPixels8Y2C(block, pixels, lineSize, h);
00606     putPixels8Y2C(block + 8, pixels + 8, lineSize, h);
00607 }
00608 
00609 void SVQ1Decoder::putPixels16XY2C(byte *block, const byte *pixels, int lineSize, int h) {
00610     putPixels8XY2C(block, pixels, lineSize, h);
00611     putPixels8XY2C(block + 8, pixels + 8, lineSize, h);
00612 }
00613 
00614 bool SVQ1Decoder::svq1MotionInterBlock(Common::BitStream32BEMSB *ss, byte *current, byte *previous, int pitch,
00615         Common::Point *motion, int x, int y) {
00616 
00617     // predict and decode motion vector
00618     Common::Point *pmv[3];
00619     pmv[0] = &motion[0];
00620     if (y == 0) {
00621         pmv[1] = pmv[2] = pmv[0];
00622     } else {
00623         pmv[1] = &motion[(x / 8) + 2];
00624         pmv[2] = &motion[(x / 8) + 4];
00625     }
00626 
00627     Common::Point mv;
00628     bool resultValid = svq1DecodeMotionVector(ss, &mv, pmv);
00629     if (!resultValid)
00630         return false;
00631 
00632     motion[0].x = motion[(x / 8) + 2].x = motion[(x / 8) + 3].x = mv.x;
00633     motion[0].y = motion[(x / 8) + 2].y = motion[(x / 8) + 3].y = mv.y;
00634 
00635     if (y + (mv.y >> 1) < 0)
00636         mv.y = 0;
00637 
00638     if (x + (mv.x >> 1) < 0)
00639         mv.x = 0;
00640 
00641     const byte *src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1)) * pitch];
00642     byte *dst = current;
00643 
00644     // Halfpel motion compensation with rounding (a + b + 1) >> 1.
00645     // 4 motion compensation functions for the 4 halfpel positions
00646     // for 16x16 blocks
00647     switch(((mv.y & 1) << 1) + (mv.x & 1)) {
00648     case 0:
00649         putPixels16C(dst, src, pitch, 16);
00650         break;
00651     case 1:
00652         putPixels16X2C(dst, src, pitch, 16);
00653         break;
00654     case 2:
00655         putPixels16Y2C(dst, src, pitch, 16);
00656         break;
00657     case 3:
00658         putPixels16XY2C(dst, src, pitch, 16);
00659         break;
00660     }
00661 
00662     return true;
00663 }
00664 
00665 bool SVQ1Decoder::svq1MotionInter4vBlock(Common::BitStream32BEMSB *ss, byte *current, byte *previous, int pitch,
00666         Common::Point *motion, int x, int y) {
00667     // predict and decode motion vector (0)
00668     Common::Point *pmv[4];
00669     pmv[0] = &motion[0];
00670     if (y == 0) {
00671         pmv[1] = pmv[2] = pmv[0];
00672     } else {
00673         pmv[1] = &motion[(x / 8) + 2];
00674         pmv[2] = &motion[(x / 8) + 4];
00675     }
00676 
00677     Common::Point mv;
00678     bool resultValid = svq1DecodeMotionVector(ss, &mv, pmv);
00679     if (!resultValid)
00680         return false;
00681 
00682     // predict and decode motion vector (1)
00683     pmv[0] = &mv;
00684     if (y == 0)
00685         pmv[1] = pmv[2] = pmv[0];
00686     else
00687         pmv[1] = &motion[(x / 8) + 3];
00688 
00689     resultValid = svq1DecodeMotionVector(ss, &motion[0], pmv);
00690     if (!resultValid)
00691         return false;
00692 
00693     // predict and decode motion vector (2)
00694     pmv[1] = &motion[0];
00695     pmv[2] = &motion[(x / 8) + 1];
00696 
00697     resultValid = svq1DecodeMotionVector(ss, &motion[(x / 8) + 2], pmv);
00698     if (!resultValid)
00699         return false;
00700 
00701     // predict and decode motion vector (3)
00702     pmv[2] = &motion[(x / 8) + 2];
00703     pmv[3] = &motion[(x / 8) + 3];
00704 
00705     resultValid = svq1DecodeMotionVector(ss, pmv[3], pmv);
00706     if (!resultValid)
00707         return false;
00708 
00709     // form predictions
00710     for (int i = 0; i < 4; i++) {
00711         int mvx = pmv[i]->x + (i & 1) * 16;
00712         int mvy = pmv[i]->y + (i >> 1) * 16;
00713 
00714         // FIXME: clipping or padding?
00715         if (y + (mvy >> 1) < 0)
00716             mvy = 0;
00717 
00718         if (x + (mvx >> 1) < 0)
00719             mvx = 0;
00720 
00721         const byte *src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1)) * pitch];
00722         byte *dst = current;
00723 
00724         // Halfpel motion compensation with rounding (a + b + 1) >> 1.
00725         // 4 motion compensation functions for the 4 halfpel positions
00726         // for 8x8 blocks
00727         switch(((mvy & 1) << 1) + (mvx & 1)) {
00728         case 0:
00729             putPixels8C(dst, src, pitch, 8);
00730             break;
00731         case 1:
00732             putPixels8X2C(dst, src, pitch, 8);
00733             break;
00734         case 2:
00735             putPixels8Y2C(dst, src, pitch, 8);
00736             break;
00737         case 3:
00738             putPixels8XY2C(dst, src, pitch, 8);
00739             break;
00740         }
00741 
00742         // select next block
00743         if (i & 1)
00744             current += (pitch - 1) * 8;
00745         else
00746             current += 8;
00747     }
00748 
00749     return true;
00750 }
00751 
00752 bool SVQ1Decoder::svq1DecodeDeltaBlock(Common::BitStream32BEMSB *ss, byte *current, byte *previous, int pitch,
00753         Common::Point *motion, int x, int y) {
00754     // get block type
00755     uint32 blockType = _blockType->getSymbol(*ss);
00756 
00757     // reset motion vectors
00758     if (blockType == SVQ1_BLOCK_SKIP || blockType == SVQ1_BLOCK_INTRA) {
00759         motion[0].x =
00760         motion[0].y =
00761         motion[(x / 8) + 2].x =
00762         motion[(x / 8) + 2].y =
00763         motion[(x / 8) + 3].x =
00764         motion[(x / 8) + 3].y = 0;
00765     }
00766 
00767     bool resultValid = true;
00768 
00769     switch (blockType) {
00770     case SVQ1_BLOCK_SKIP:
00771         svq1SkipBlock(current, previous, pitch, x, y);
00772         break;
00773     case SVQ1_BLOCK_INTER:
00774         resultValid = svq1MotionInterBlock(ss, current, previous, pitch, motion, x, y);
00775         if (!resultValid) {
00776             warning("svq1MotionInterBlock decode failure");
00777             break;
00778         }
00779         resultValid = svq1DecodeBlockNonIntra(ss, current, pitch);
00780         break;
00781     case SVQ1_BLOCK_INTER_4V:
00782         resultValid = svq1MotionInter4vBlock(ss, current, previous, pitch, motion, x, y);
00783         if (!resultValid) {
00784             warning("svq1MotionInter4vBlock decode failure");
00785             break;
00786         }
00787         resultValid = svq1DecodeBlockNonIntra(ss, current, pitch);
00788         break;
00789     case SVQ1_BLOCK_INTRA:
00790         resultValid = svq1DecodeBlockIntra(ss, current, pitch);
00791         break;
00792     }
00793 
00794     return resultValid;
00795 }
00796 
00797 } // End of namespace Image


Generated on Sat May 25 2019 05:00:54 for ResidualVM by doxygen 1.7.1
curved edge   curved edge