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

psx_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 // PlayStation Stream demuxer and XA audio decoder based on FFmpeg/libav
00024 // MDEC video emulation based on http://kenai.com/downloads/jpsxdec/Old/PlayStation1_STR_format1-00.txt
00025 
00026 #include "audio/audiostream.h"
00027 #include "audio/decoders/raw.h"
00028 #include "common/bitstream.h"
00029 #include "common/huffman.h"
00030 #include "common/stream.h"
00031 #include "common/system.h"
00032 #include "common/textconsole.h"
00033 #include "graphics/yuv_to_rgb.h"
00034 
00035 #include "video/psx_decoder.h"
00036 
00037 namespace Video {
00038 
00039 // Here are the codes/lengths/symbols that are used for decoding
00040 // DC coefficients (version 3 frames only)
00041 
00042 #define DC_CODE_COUNT 9
00043 #define DC_HUFF_VAL(b, n, p) (((b) << 16) | ((n) << 8) | (p))
00044 #define GET_DC_BITS(x) ((x) >> 16)
00045 #define GET_DC_NEG(x) ((int)(((x) >> 8) & 0xff))
00046 #define GET_DC_POS(x) ((int)((x) & 0xff))
00047 
00048 static const uint32 s_huffmanDCChromaCodes[DC_CODE_COUNT] = {
00049     254, 126, 62, 30, 14, 6, 2, 1, 0
00050 };
00051 
00052 static const byte s_huffmanDCChromaLengths[DC_CODE_COUNT] = {
00053     8, 7, 6, 5, 4, 3, 2, 2, 2
00054 };
00055 
00056 static const uint32 s_huffmanDCLumaCodes[DC_CODE_COUNT] = {
00057     126, 62, 30, 14, 6, 5, 1, 0, 4
00058 };
00059 
00060 static const byte s_huffmanDCLumaLengths[DC_CODE_COUNT] = {
00061     7, 6, 5, 4, 3, 3, 2, 2, 3
00062 };
00063 
00064 static const uint32 s_huffmanDCSymbols[DC_CODE_COUNT] = {
00065     DC_HUFF_VAL(8, 255, 128), DC_HUFF_VAL(7, 127, 64), DC_HUFF_VAL(6, 63, 32),
00066     DC_HUFF_VAL(5, 31, 16), DC_HUFF_VAL(4, 15, 8), DC_HUFF_VAL(3, 7, 4),
00067     DC_HUFF_VAL(2, 3, 2), DC_HUFF_VAL(1, 1, 1), DC_HUFF_VAL(0, 0, 0)
00068 };
00069 
00070 // Here are the codes/lengths/symbols that are used for decoding
00071 // DC coefficients (version 2 and 3 frames)
00072 
00073 #define AC_CODE_COUNT 113
00074 #define AC_HUFF_VAL(z, a) ((z << 8) | a)
00075 #define ESCAPE_CODE  ((uint32)-1) // arbitrary, just so we can tell what code it is
00076 #define END_OF_BLOCK ((uint32)-2) // arbitrary, just so we can tell what code it is
00077 #define GET_AC_ZERO_RUN(code) (code >> 8)
00078 #define GET_AC_COEFFICIENT(code) ((int)(code & 0xff))
00079 
00080 static const uint32 s_huffmanACCodes[AC_CODE_COUNT] = {
00081     // Regular codes
00082     3, 3, 4, 5, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7,
00083     32, 33, 34, 35, 36, 37, 38, 39, 8, 9, 10, 11,
00084     12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
00085     23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17,
00086     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
00087     29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23,
00088     24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18,
00089     19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
00090     30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24,
00091     25, 26, 27, 28, 29, 30, 31,
00092 
00093     // Escape code
00094     1,
00095     // End of block code
00096     2
00097 };
00098 
00099 static const byte s_huffmanACLengths[AC_CODE_COUNT] = {
00100     // Regular codes
00101     2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
00102     8, 8, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10,
00103     10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
00104     12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13,
00105     13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
00106     13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
00107     14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
00108     15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
00109     15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
00110     16, 16, 16, 16, 16, 16,
00111 
00112     // Escape code
00113     6,
00114     // End of block code
00115     2
00116 };
00117 
00118 static const uint32 s_huffmanACSymbols[AC_CODE_COUNT] = {
00119     // Regular codes
00120     AC_HUFF_VAL(0, 1), AC_HUFF_VAL(1, 1), AC_HUFF_VAL(0, 2), AC_HUFF_VAL(2, 1), AC_HUFF_VAL(0, 3),
00121     AC_HUFF_VAL(4, 1), AC_HUFF_VAL(3, 1), AC_HUFF_VAL(7, 1), AC_HUFF_VAL(6, 1), AC_HUFF_VAL(1, 2),
00122     AC_HUFF_VAL(5, 1), AC_HUFF_VAL(2, 2), AC_HUFF_VAL(9, 1), AC_HUFF_VAL(0, 4), AC_HUFF_VAL(8, 1),
00123     AC_HUFF_VAL(13, 1), AC_HUFF_VAL(0, 6), AC_HUFF_VAL(12, 1), AC_HUFF_VAL(11, 1), AC_HUFF_VAL(3, 2),
00124     AC_HUFF_VAL(1, 3), AC_HUFF_VAL(0, 5), AC_HUFF_VAL(10, 1), AC_HUFF_VAL(16, 1), AC_HUFF_VAL(5, 2),
00125     AC_HUFF_VAL(0, 7), AC_HUFF_VAL(2, 3), AC_HUFF_VAL(1, 4), AC_HUFF_VAL(15, 1), AC_HUFF_VAL(14, 1),
00126     AC_HUFF_VAL(4, 2), AC_HUFF_VAL(0, 11), AC_HUFF_VAL(8, 2), AC_HUFF_VAL(4, 3), AC_HUFF_VAL(0, 10),
00127     AC_HUFF_VAL(2, 4), AC_HUFF_VAL(7, 2), AC_HUFF_VAL(21, 1), AC_HUFF_VAL(20, 1), AC_HUFF_VAL(0, 9),
00128     AC_HUFF_VAL(19, 1), AC_HUFF_VAL(18, 1), AC_HUFF_VAL(1, 5), AC_HUFF_VAL(3, 3), AC_HUFF_VAL(0, 8),
00129     AC_HUFF_VAL(6, 2), AC_HUFF_VAL(17, 1), AC_HUFF_VAL(10, 2), AC_HUFF_VAL(9, 2), AC_HUFF_VAL(5, 3),
00130     AC_HUFF_VAL(3, 4), AC_HUFF_VAL(2, 5), AC_HUFF_VAL(1, 7), AC_HUFF_VAL(1, 6), AC_HUFF_VAL(0, 15),
00131     AC_HUFF_VAL(0, 14), AC_HUFF_VAL(0, 13), AC_HUFF_VAL(0, 12), AC_HUFF_VAL(26, 1), AC_HUFF_VAL(25, 1),
00132     AC_HUFF_VAL(24, 1), AC_HUFF_VAL(23, 1), AC_HUFF_VAL(22, 1), AC_HUFF_VAL(0, 31), AC_HUFF_VAL(0, 30),
00133     AC_HUFF_VAL(0, 29), AC_HUFF_VAL(0, 28), AC_HUFF_VAL(0, 27), AC_HUFF_VAL(0, 26), AC_HUFF_VAL(0, 25),
00134     AC_HUFF_VAL(0, 24), AC_HUFF_VAL(0, 23), AC_HUFF_VAL(0, 22), AC_HUFF_VAL(0, 21), AC_HUFF_VAL(0, 20),
00135     AC_HUFF_VAL(0, 19), AC_HUFF_VAL(0, 18), AC_HUFF_VAL(0, 17), AC_HUFF_VAL(0, 16), AC_HUFF_VAL(0, 40),
00136     AC_HUFF_VAL(0, 39), AC_HUFF_VAL(0, 38), AC_HUFF_VAL(0, 37), AC_HUFF_VAL(0, 36), AC_HUFF_VAL(0, 35),
00137     AC_HUFF_VAL(0, 34), AC_HUFF_VAL(0, 33), AC_HUFF_VAL(0, 32), AC_HUFF_VAL(1, 14), AC_HUFF_VAL(1, 13),
00138     AC_HUFF_VAL(1, 12), AC_HUFF_VAL(1, 11), AC_HUFF_VAL(1, 10), AC_HUFF_VAL(1, 9), AC_HUFF_VAL(1, 8),
00139     AC_HUFF_VAL(1, 18), AC_HUFF_VAL(1, 17), AC_HUFF_VAL(1, 16), AC_HUFF_VAL(1, 15), AC_HUFF_VAL(6, 3),
00140     AC_HUFF_VAL(16, 2), AC_HUFF_VAL(15, 2), AC_HUFF_VAL(14, 2), AC_HUFF_VAL(13, 2), AC_HUFF_VAL(12, 2),
00141     AC_HUFF_VAL(11, 2), AC_HUFF_VAL(31, 1), AC_HUFF_VAL(30, 1), AC_HUFF_VAL(29, 1), AC_HUFF_VAL(28, 1),
00142     AC_HUFF_VAL(27, 1),
00143 
00144     // Escape code
00145     ESCAPE_CODE,
00146     // End of block code
00147     END_OF_BLOCK
00148 };
00149 
00150 PSXStreamDecoder::PSXStreamDecoder(CDSpeed speed, uint32 frameCount) : _speed(speed), _frameCount(frameCount) {
00151     _stream = 0;
00152     _videoTrack = 0;
00153     _audioTrack = 0;
00154 }
00155 
00156 PSXStreamDecoder::~PSXStreamDecoder() {
00157     close();
00158 }
00159 
00160 #define RAW_CD_SECTOR_SIZE 2352
00161 
00162 #define CDXA_TYPE_MASK     0x0E
00163 #define CDXA_TYPE_DATA     0x08
00164 #define CDXA_TYPE_AUDIO    0x04
00165 #define CDXA_TYPE_VIDEO    0x02
00166 
00167 bool PSXStreamDecoder::loadStream(Common::SeekableReadStream *stream) {
00168     close();
00169 
00170     _stream = stream;
00171     readNextPacket();
00172 
00173     return true;
00174 }
00175 
00176 void PSXStreamDecoder::close() {
00177     VideoDecoder::close();
00178     _audioTrack = 0;
00179     _videoTrack = 0;
00180     _frameCount = 0;
00181 
00182     delete _stream;
00183     _stream = 0;
00184 }
00185 
00186 #define VIDEO_DATA_CHUNK_SIZE   2016
00187 #define VIDEO_DATA_HEADER_SIZE  56
00188 
00189 void PSXStreamDecoder::readNextPacket() {
00190     Common::SeekableReadStream *sector = 0;
00191     byte *partialFrame = 0;
00192     int sectorsRead = 0;
00193 
00194     while (_stream->pos() < _stream->size()) {
00195         sector = readSector();
00196         sectorsRead++;
00197 
00198         if (!sector)
00199             error("Corrupt PSX stream sector");
00200 
00201         sector->seek(0x11);
00202         byte track = sector->readByte();
00203         if (track >= 32)
00204             error("Bad PSX stream track");
00205 
00206         byte sectorType = sector->readByte() & CDXA_TYPE_MASK;
00207 
00208         switch (sectorType) {
00209         case CDXA_TYPE_DATA:
00210         case CDXA_TYPE_VIDEO:
00211             if (track == 1) {
00212                 if (!_videoTrack) {
00213                     _videoTrack = new PSXVideoTrack(sector, _speed, _frameCount);
00214                     addTrack(_videoTrack);
00215                 }
00216 
00217                 sector->seek(28);
00218                 uint16 curSector = sector->readUint16LE();
00219                 uint16 sectorCount = sector->readUint16LE();
00220                 sector->readUint32LE();
00221                 uint16 frameSize = sector->readUint32LE();
00222 
00223                 if (curSector >= sectorCount)
00224                     error("Bad sector");
00225 
00226                 if (!partialFrame)
00227                     partialFrame = (byte *)malloc(sectorCount * VIDEO_DATA_CHUNK_SIZE);
00228 
00229                 sector->seek(VIDEO_DATA_HEADER_SIZE);
00230                 sector->read(partialFrame + curSector * VIDEO_DATA_CHUNK_SIZE, VIDEO_DATA_CHUNK_SIZE);
00231 
00232                 if (curSector == sectorCount - 1) {
00233                     // Done assembling the frame
00234                     Common::BitStreamMemoryStream *frame = new Common::BitStreamMemoryStream(partialFrame, frameSize, DisposeAfterUse::YES);
00235 
00236                     _videoTrack->decodeFrame(frame, sectorsRead);
00237 
00238                     delete frame;
00239                     delete sector;
00240                     return;
00241                 }
00242             } else
00243                 error("Unhandled multi-track video");
00244             break;
00245         case CDXA_TYPE_AUDIO:
00246             // We only handle one audio channel so far
00247             if (track == 1) {
00248                 if (!_audioTrack) {
00249                     _audioTrack = new PSXAudioTrack(sector, getSoundType());
00250                     addTrack(_audioTrack);
00251                 }
00252 
00253                 _audioTrack->queueAudioFromSector(sector);
00254             } else {
00255                 warning("Unhandled multi-track audio");
00256             }
00257             break;
00258         default:
00259             // This shows up way too often, but the other sectors
00260             // are safe to ignore
00261             //warning("Unknown PSX sector type 0x%x", sectorType);
00262             break;
00263         }
00264 
00265         delete sector;
00266     }
00267 
00268     if (_stream->pos() >= _stream->size()) {
00269         if (_videoTrack)
00270             _videoTrack->setEndOfTrack();
00271 
00272         if (_audioTrack)
00273             _audioTrack->setEndOfTrack();
00274     }
00275 }
00276 
00277 bool PSXStreamDecoder::useAudioSync() const {
00278     // Audio sync is disabled since most audio data comes after video
00279     // data.
00280     return false;
00281 }
00282 
00283 static const byte s_syncHeader[12] = { 0x00, 0xff ,0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
00284 
00285 Common::SeekableReadStream *PSXStreamDecoder::readSector() {
00286     assert(_stream);
00287 
00288     Common::SeekableReadStream *stream = _stream->readStream(RAW_CD_SECTOR_SIZE);
00289 
00290     byte syncHeader[12];
00291     stream->read(syncHeader, 12);
00292     if (!memcmp(s_syncHeader, syncHeader, 12))
00293         return stream;
00294 
00295     return 0;
00296 }
00297 
00298 // Ha! It's palindromic!
00299 #define AUDIO_DATA_CHUNK_SIZE   2304
00300 #define AUDIO_DATA_SAMPLE_COUNT 4032
00301 
00302 static const int s_xaTable[5][2] = {
00303    {   0,   0 },
00304    {  60,   0 },
00305    { 115, -52 },
00306    {  98, -55 },
00307    { 122, -60 }
00308 };
00309 
00310 PSXStreamDecoder::PSXAudioTrack::PSXAudioTrack(Common::SeekableReadStream *sector, Audio::Mixer::SoundType soundType) :
00311         AudioTrack(soundType) {
00312     assert(sector);
00313     _endOfTrack = false;
00314 
00315     sector->seek(19);
00316     byte format = sector->readByte();
00317     bool stereo = (format & (1 << 0)) != 0;
00318     uint rate = (format & (1 << 2)) ? 18900 : 37800;
00319     _audStream = Audio::makeQueuingAudioStream(rate, stereo);
00320 
00321     memset(&_adpcmStatus, 0, sizeof(_adpcmStatus));
00322 }
00323 
00324 PSXStreamDecoder::PSXAudioTrack::~PSXAudioTrack() {
00325     delete _audStream;
00326 }
00327 
00328 bool PSXStreamDecoder::PSXAudioTrack::endOfTrack() const {
00329     return AudioTrack::endOfTrack() && _endOfTrack;
00330 }
00331 
00332 void PSXStreamDecoder::PSXAudioTrack::queueAudioFromSector(Common::SeekableReadStream *sector) {
00333     assert(sector);
00334 
00335     sector->seek(24);
00336 
00337     // This XA audio is different (yet similar) from normal XA audio! Watch out!
00338     // TODO: It's probably similar enough to normal XA that we can merge it somehow...
00339     // TODO: RTZ PSX needs the same audio code in a regular AudioStream class. Probably
00340     // will do something similar to QuickTime and creating a base class 'ISOMode2Parser'
00341     // or something similar.
00342     byte *buf = new byte[AUDIO_DATA_CHUNK_SIZE];
00343     sector->read(buf, AUDIO_DATA_CHUNK_SIZE);
00344 
00345     int channels = _audStream->isStereo() ? 2 : 1;
00346     int16 *dst = new int16[AUDIO_DATA_SAMPLE_COUNT];
00347     int16 *leftChannel = dst;
00348     int16 *rightChannel = dst + 1;
00349 
00350     for (byte *src = buf; src < buf + AUDIO_DATA_CHUNK_SIZE; src += 128) {
00351         for (int i = 0; i < 4; i++) {
00352             int shift = 12 - (src[4 + i * 2] & 0xf);
00353             int filter = src[4 + i * 2] >> 4;
00354             int f0 = s_xaTable[filter][0];
00355             int f1 = s_xaTable[filter][1];
00356             int16 s_1 = _adpcmStatus[0].sample[0];
00357             int16 s_2 = _adpcmStatus[0].sample[1];
00358 
00359             for (int j = 0; j < 28; j++) {
00360                 byte d = src[16 + i + j * 4];
00361                 int t = (int8)(d << 4) >> 4;
00362                 int s = (t << shift) + ((s_1 * f0 + s_2 * f1 + 32) >> 6);
00363                 s_2 = s_1;
00364                 s_1 = CLIP<int>(s, -32768, 32767);
00365                 *leftChannel = s_1;
00366                 leftChannel += channels;
00367             }
00368 
00369             if (channels == 2) {
00370                 _adpcmStatus[0].sample[0] = s_1;
00371                 _adpcmStatus[0].sample[1] = s_2;
00372                 s_1 = _adpcmStatus[1].sample[0];
00373                 s_2 = _adpcmStatus[1].sample[1];
00374             }
00375 
00376             shift = 12 - (src[5 + i * 2] & 0xf);
00377             filter = src[5 + i * 2] >> 4;
00378             f0 = s_xaTable[filter][0];
00379             f1 = s_xaTable[filter][1];
00380 
00381             for (int j = 0; j < 28; j++) {
00382                 byte d = src[16 + i + j * 4];
00383                 int t = (int8)d >> 4;
00384                 int s = (t << shift) + ((s_1 * f0 + s_2 * f1 + 32) >> 6);
00385                 s_2 = s_1;
00386                 s_1 = CLIP<int>(s, -32768, 32767);
00387 
00388                 if (channels == 2) {
00389                     *rightChannel = s_1;
00390                     rightChannel += 2;
00391                 } else {
00392                     *leftChannel++ = s_1;
00393                 }
00394             }
00395 
00396             if (channels == 2) {
00397                 _adpcmStatus[1].sample[0] = s_1;
00398                 _adpcmStatus[1].sample[1] = s_2;
00399             } else {
00400                 _adpcmStatus[0].sample[0] = s_1;
00401                 _adpcmStatus[0].sample[1] = s_2;
00402             }
00403         }
00404     }
00405 
00406     int flags = Audio::FLAG_16BITS;
00407 
00408     if (_audStream->isStereo())
00409         flags |= Audio::FLAG_STEREO;
00410 
00411 #ifdef SCUMM_LITTLE_ENDIAN
00412     flags |= Audio::FLAG_LITTLE_ENDIAN;
00413 #endif
00414 
00415     _audStream->queueBuffer((byte *)dst, AUDIO_DATA_SAMPLE_COUNT * 2, DisposeAfterUse::YES, flags);
00416     delete[] buf;
00417 }
00418 
00419 Audio::AudioStream *PSXStreamDecoder::PSXAudioTrack::getAudioStream() const {
00420     return _audStream;
00421 }
00422 
00423 
00424 PSXStreamDecoder::PSXVideoTrack::PSXVideoTrack(Common::SeekableReadStream *firstSector, CDSpeed speed, int frameCount) : _nextFrameStartTime(0, speed), _frameCount(frameCount) {
00425     assert(firstSector);
00426 
00427     firstSector->seek(40);
00428     uint16 width = firstSector->readUint16LE();
00429     uint16 height = firstSector->readUint16LE();
00430     _surface = new Graphics::Surface();
00431     _surface->create(width, height, g_system->getScreenFormat());
00432 
00433     _macroBlocksW = (width + 15) / 16;
00434     _macroBlocksH = (height + 15) / 16;
00435     _yBuffer = new byte[_macroBlocksW * _macroBlocksH * 16 * 16];
00436     _cbBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8];
00437     _crBuffer = new byte[_macroBlocksW * _macroBlocksH * 8 * 8];
00438 
00439     _endOfTrack = false;
00440     _curFrame = -1;
00441     _acHuffman = new HuffmanDecoder(0, AC_CODE_COUNT, s_huffmanACCodes, s_huffmanACLengths, s_huffmanACSymbols);
00442     _dcHuffmanChroma = new HuffmanDecoder(0, DC_CODE_COUNT, s_huffmanDCChromaCodes, s_huffmanDCChromaLengths, s_huffmanDCSymbols);
00443     _dcHuffmanLuma = new HuffmanDecoder(0, DC_CODE_COUNT, s_huffmanDCLumaCodes, s_huffmanDCLumaLengths, s_huffmanDCSymbols);
00444 }
00445 
00446 PSXStreamDecoder::PSXVideoTrack::~PSXVideoTrack() {
00447     _surface->free();
00448     delete _surface;
00449 
00450     delete[] _yBuffer;
00451     delete[] _cbBuffer;
00452     delete[] _crBuffer;
00453     delete _acHuffman;
00454     delete _dcHuffmanChroma;
00455     delete _dcHuffmanLuma;
00456 }
00457 
00458 uint32 PSXStreamDecoder::PSXVideoTrack::getNextFrameStartTime() const {
00459     return _nextFrameStartTime.msecs();
00460 }
00461 
00462 const Graphics::Surface *PSXStreamDecoder::PSXVideoTrack::decodeNextFrame() {
00463     return _surface;
00464 }
00465 
00466 void PSXStreamDecoder::PSXVideoTrack::decodeFrame(Common::BitStreamMemoryStream *frame, uint sectorCount) {
00467     // A frame is essentially an MPEG-1 intra frame
00468 
00469     Common::BitStreamMemory16LEMSB bits(frame);
00470 
00471     bits.skip(16); // unknown
00472     bits.skip(16); // 0x3800
00473     uint16 scale = bits.getBits(16);
00474     uint16 version = bits.getBits(16);
00475 
00476     if (version != 2 && version != 3)
00477         error("Unknown PSX stream frame version");
00478 
00479     // Initalize default v3 DC here
00480     _lastDC[0] = _lastDC[1] = _lastDC[2] = 0;
00481 
00482     for (int mbX = 0; mbX < _macroBlocksW; mbX++)
00483         for (int mbY = 0; mbY < _macroBlocksH; mbY++)
00484             decodeMacroBlock(&bits, mbX, mbY, scale, version);
00485 
00486     // Output data onto the frame
00487     YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleFull, _yBuffer, _cbBuffer, _crBuffer, _surface->w, _surface->h, _macroBlocksW * 16, _macroBlocksW * 8);
00488 
00489     _curFrame++;
00490 
00491     // Increase the time by the amount of sectors we read
00492     // One may notice that this is still not the most precise
00493     // method since a frame takes up the time its sectors took
00494     // up instead of the amount of time it takes the next frame
00495     // to be read from the sectors. The actual frame rate should
00496     // be constant instead of variable, so the slight difference
00497     // in a frame's showing time is negligible (1/150 of a second).
00498     _nextFrameStartTime = _nextFrameStartTime.addFrames(sectorCount);
00499 }
00500 
00501 void PSXStreamDecoder::PSXVideoTrack::decodeMacroBlock(Common::BitStreamMemory16LEMSB *bits, int mbX, int mbY, uint16 scale, uint16 version) {
00502     int pitchY = _macroBlocksW * 16;
00503     int pitchC = _macroBlocksW * 8;
00504 
00505     // Note the strange order of red before blue
00506     decodeBlock(bits, _crBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version, kPlaneV);
00507     decodeBlock(bits, _cbBuffer + (mbY * pitchC + mbX) * 8, pitchC, scale, version, kPlaneU);
00508     decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16, pitchY, scale, version, kPlaneY);
00509     decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8, pitchY, scale, version, kPlaneY);
00510     decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY, pitchY, scale, version, kPlaneY);
00511     decodeBlock(bits, _yBuffer + (mbY * pitchY + mbX) * 16 + 8 * pitchY + 8, pitchY, scale, version, kPlaneY);
00512 }
00513 
00514 // Standard JPEG/MPEG zig zag table
00515 static const byte s_zigZagTable[8 * 8] = {
00516      0,  1,  5,  6, 14, 15, 27, 28,
00517      2,  4,  7, 13, 16, 26, 29, 42,
00518      3,  8, 12, 17, 25, 30, 41, 43,
00519      9, 11, 18, 24, 31, 40, 44, 53,
00520     10, 19, 23, 32, 39, 45, 52, 54,
00521     20, 22, 33, 38, 46, 51, 55, 60,
00522     21, 34, 37, 47, 50, 56, 59, 61,
00523     35, 36, 48, 49, 57, 58, 62, 63
00524 };
00525 
00526 // One byte different from the standard MPEG-1 table
00527 static const byte s_quantizationTable[8 * 8] = {
00528      2, 16, 19, 22, 26, 27, 29, 34,
00529     16, 16, 22, 24, 27, 29, 34, 37,
00530     19, 22, 26, 27, 29, 34, 34, 38,
00531     22, 22, 26, 27, 29, 34, 37, 40,
00532     22, 26, 27, 29, 32, 35, 40, 48,
00533     26, 27, 29, 32, 35, 40, 48, 58,
00534     26, 27, 29, 34, 38, 46, 56, 69,
00535     27, 29, 35, 38, 46, 56, 69, 83
00536 };
00537 
00538 void PSXStreamDecoder::PSXVideoTrack::dequantizeBlock(int *coefficients, float *block, uint16 scale) {
00539     // Dequantize the data, un-zig-zagging as we go along
00540     for (int i = 0; i < 8 * 8; i++) {
00541         if (i == 0) // Special case for the DC coefficient
00542             block[i] = coefficients[i] * s_quantizationTable[i];
00543         else
00544             block[i] = (float)coefficients[s_zigZagTable[i]] * s_quantizationTable[i] * scale / 8;
00545     }
00546 }
00547 
00548 int PSXStreamDecoder::PSXVideoTrack::readDC(Common::BitStreamMemory16LEMSB *bits, uint16 version, PlaneType plane) {
00549     // Version 2 just has its coefficient as 10-bits
00550     if (version == 2)
00551         return readSignedCoefficient(bits);
00552 
00553     // Version 3 has it stored as huffman codes as a difference from the previous DC value
00554 
00555     HuffmanDecoder *huffman = (plane == kPlaneY) ? _dcHuffmanLuma : _dcHuffmanChroma;
00556 
00557     uint32 symbol = huffman->getSymbol(*bits);
00558     int dc = 0;
00559 
00560     if (GET_DC_BITS(symbol) != 0) {
00561         bool negative = (bits->getBit() == 0);
00562         dc = bits->getBits(GET_DC_BITS(symbol) - 1);
00563 
00564         if (negative)
00565             dc -= GET_DC_NEG(symbol);
00566         else
00567             dc += GET_DC_POS(symbol);
00568     }
00569 
00570     _lastDC[plane] += dc * 4; // convert from 8-bit to 10-bit
00571     return _lastDC[plane];
00572 }
00573 
00574 #define BLOCK_OVERFLOW_CHECK() \
00575     if (count > 63) \
00576         error("PSXStreamDecoder::readAC(): Too many coefficients")
00577 
00578 void PSXStreamDecoder::PSXVideoTrack::readAC(Common::BitStreamMemory16LEMSB *bits, int *block) {
00579     // Clear the block first
00580     for (int i = 0; i < 63; i++)
00581         block[i] = 0;
00582 
00583     int count = 0;
00584 
00585     while (!bits->eos()) {
00586         uint32 symbol = _acHuffman->getSymbol(*bits);
00587 
00588         if (symbol == ESCAPE_CODE) {
00589             // The escape code!
00590             int zeroes = bits->getBits(6);
00591             count += zeroes + 1;
00592             BLOCK_OVERFLOW_CHECK();
00593             block += zeroes;
00594             *block++ = readSignedCoefficient(bits);
00595         } else if (symbol == END_OF_BLOCK) {
00596             // We're done
00597             break;
00598         } else {
00599             // Normal huffman code
00600             int zeroes = GET_AC_ZERO_RUN(symbol);
00601             count += zeroes + 1;
00602             BLOCK_OVERFLOW_CHECK();
00603             block += zeroes;
00604 
00605             if (bits->getBit())
00606                 *block++ = -GET_AC_COEFFICIENT(symbol);
00607             else
00608                 *block++ = GET_AC_COEFFICIENT(symbol);
00609         }
00610     }
00611 }
00612 
00613 int PSXStreamDecoder::PSXVideoTrack::readSignedCoefficient(Common::BitStreamMemory16LEMSB *bits) {
00614     uint val = bits->getBits(10);
00615 
00616     // extend the sign
00617     uint shift = 8 * sizeof(int) - 10;
00618     return (int)(val << shift) >> shift;
00619 }
00620 
00621 // IDCT table built with :
00622 // _idct8x8[x][y] = cos(((2 * x + 1) * y) * (M_PI / 16.0)) * 0.5;
00623 // _idct8x8[x][y] /= sqrt(2.0) if y == 0
00624 static const double s_idct8x8[8][8] = {
00625     { 0.353553390593274,  0.490392640201615,  0.461939766255643,  0.415734806151273,  0.353553390593274,  0.277785116509801,  0.191341716182545,  0.097545161008064 },
00626     { 0.353553390593274,  0.415734806151273,  0.191341716182545, -0.097545161008064, -0.353553390593274, -0.490392640201615, -0.461939766255643, -0.277785116509801 },
00627     { 0.353553390593274,  0.277785116509801, -0.191341716182545, -0.490392640201615, -0.353553390593274,  0.097545161008064,  0.461939766255643,  0.415734806151273 },
00628     { 0.353553390593274,  0.097545161008064, -0.461939766255643, -0.277785116509801,  0.353553390593274,  0.415734806151273, -0.191341716182545, -0.490392640201615 },
00629     { 0.353553390593274, -0.097545161008064, -0.461939766255643,  0.277785116509801,  0.353553390593274, -0.415734806151273, -0.191341716182545,  0.490392640201615 },
00630     { 0.353553390593274, -0.277785116509801, -0.191341716182545,  0.490392640201615, -0.353553390593273, -0.097545161008064,  0.461939766255643, -0.415734806151273 },
00631     { 0.353553390593274, -0.415734806151273,  0.191341716182545,  0.097545161008064, -0.353553390593274,  0.490392640201615, -0.461939766255643,  0.277785116509801 },
00632     { 0.353553390593274, -0.490392640201615,  0.461939766255643, -0.415734806151273,  0.353553390593273, -0.277785116509801,  0.191341716182545, -0.097545161008064 }
00633 };
00634 
00635 void PSXStreamDecoder::PSXVideoTrack::idct(float *dequantData, float *result) {
00636     // IDCT code based on JPEG's IDCT code
00637     // TODO: Switch to the integer-based one mentioned in the docs
00638     // This is by far the costliest operation here
00639 
00640     float tmp[8 * 8];
00641 
00642     // Apply 1D IDCT to rows
00643     for (int y = 0; y < 8; y++) {
00644         for (int x = 0; x < 8; x++) {
00645             tmp[y + x * 8] = dequantData[0] * s_idct8x8[x][0]
00646                             + dequantData[1] * s_idct8x8[x][1]
00647                             + dequantData[2] * s_idct8x8[x][2]
00648                             + dequantData[3] * s_idct8x8[x][3]
00649                             + dequantData[4] * s_idct8x8[x][4]
00650                             + dequantData[5] * s_idct8x8[x][5]
00651                             + dequantData[6] * s_idct8x8[x][6]
00652                             + dequantData[7] * s_idct8x8[x][7];
00653         }
00654 
00655         dequantData += 8;
00656     }
00657 
00658     // Apply 1D IDCT to columns
00659     for (int x = 0; x < 8; x++) {
00660         const float *u = tmp + x * 8;
00661         for (int y = 0; y < 8; y++) {
00662             result[y * 8 + x] = u[0] * s_idct8x8[y][0]
00663                                 + u[1] * s_idct8x8[y][1]
00664                                 + u[2] * s_idct8x8[y][2]
00665                                 + u[3] * s_idct8x8[y][3]
00666                                 + u[4] * s_idct8x8[y][4]
00667                                 + u[5] * s_idct8x8[y][5]
00668                                 + u[6] * s_idct8x8[y][6]
00669                                 + u[7] * s_idct8x8[y][7];
00670         }
00671     }
00672 }
00673 
00674 void PSXStreamDecoder::PSXVideoTrack::decodeBlock(Common::BitStreamMemory16LEMSB *bits, byte *block, int pitch, uint16 scale, uint16 version, PlaneType plane) {
00675     // Version 2 just has signed 10 bits for DC
00676     // Version 3 has them huffman coded
00677     int coefficients[8 * 8];
00678     coefficients[0] = readDC(bits, version, plane);
00679     readAC(bits, &coefficients[1]); // Read in the AC
00680 
00681     // Dequantize
00682     float dequantData[8 * 8];
00683     dequantizeBlock(coefficients, dequantData, scale);
00684 
00685     // Perform IDCT
00686     float idctData[8 * 8];
00687     idct(dequantData, idctData);
00688 
00689     // Now output the data
00690     for (int y = 0; y < 8; y++) {
00691         byte *dst = block + pitch * y;
00692 
00693         // Convert the result to be in the range [0, 255]
00694         for (int x = 0; x < 8; x++)
00695             *dst++ = (int)CLIP<float>(idctData[y * 8 + x], -128.0f, 127.0f) + 128;
00696     }
00697 }
00698 
00699 
00700 } // End of namespace Video


Generated on Sat May 18 2019 05:01:13 for ResidualVM by doxygen 1.7.1
curved edge   curved edge