Ticket #9141: vid_dec_graphics.diff

File vid_dec_graphics.diff, 52.7 KB (added by SF/mthreepwood, 16 years ago)

Patch (graphics directory) against r49069

  • graphics/module.mk

     
    2626        video/flic_decoder.o \
    2727        video/mpeg_player.o \
    2828        video/smk_decoder.o \
    29         video/video_player.o \
     29        video/video_decoder.o \
    3030        video/codecs/msrle.o \
    3131        video/codecs/msvideo1.o \
    3232        video/coktelvideo/indeo3.o \
  • graphics/video/video_decoder.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/graphics/video/video_decoder.h $
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef GRAPHICS_VIDEO_PLAYER_H
     27#define GRAPHICS_VIDEO_PLAYER_H
     28
     29#include "common/events.h"
     30#include "common/list.h"
     31#include "common/rational.h"
     32#include "common/stream.h"
     33
     34#include "graphics/surface.h"
     35#include "graphics/pixelformat.h"
     36
     37namespace Common {
     38        class SeekableReadStream;
     39}
     40
     41namespace Graphics {
     42
     43/**
     44 * Implementation of a generic video decoder
     45 */
     46class VideoDecoder {
     47public:
     48        VideoDecoder();
     49        virtual ~VideoDecoder() {}
     50
     51        /**
     52         * Returns the width of the video
     53         * @return the width of the video
     54         */
     55        virtual uint16 getWidth() const = 0;
     56
     57        /**
     58         * Returns the height of the video
     59         * @return the height of the video
     60         */
     61        virtual uint16 getHeight() const = 0;
     62
     63        /**
     64         * Returns the current frame number of the video
     65         * @return the last frame decoded by the video
     66         */
     67        virtual int32 getCurFrame() const { return _curFrame; }
     68
     69        /**
     70         * Returns the amount of frames in the video
     71         * @return the amount of frames in the video
     72         */
     73        virtual uint32 getFrameCount() const = 0;
     74
     75        /**
     76         * Returns the time (in ms) that the video has been running
     77         */
     78        virtual uint32 getElapsedTime() const;
     79
     80        /**
     81         * Returns whether a frame should be decoded or not
     82         * @return whether a frame should be decoded or not
     83         */
     84        virtual bool needsUpdate() const;
     85
     86        /**
     87         * Load a video file
     88         * @param filename      the filename to load
     89         */
     90        virtual bool loadFile(const Common::String &filename);
     91
     92        /**
     93         * Load a video file
     94         * @param stream  the stream to load
     95         */
     96        virtual bool load(Common::SeekableReadStream &stream) = 0;
     97
     98        /**
     99         * Close a video file
     100         */
     101        virtual void close() = 0;
     102
     103        /**
     104         * Returns if a video file is loaded or not
     105         */
     106        virtual bool isVideoLoaded() const = 0;
     107
     108        /**
     109         * Decode the next frame and return the frame's surface
     110         * @note the return surface should *not* be freed
     111         * @note this may return 0, in which case the last frame should be kept on screen
     112         */
     113        virtual Surface *decodeNextFrame() = 0;
     114
     115        /**
     116         * Get the pixel format of the video
     117         */
     118        virtual PixelFormat getPixelFormat() const = 0;
     119
     120        /**
     121         * Get the palette for the video in RGB format (if 8bpp or less)
     122         */
     123        virtual byte *getPalette() { return 0; }
     124
     125        /**
     126         * Returns if the palette is dirty or not
     127         */
     128        virtual bool hasDirtyPalette() const { return false; }
     129
     130        /**
     131         * Add the time the video has been paused to maintain sync
     132         */
     133        virtual void addPauseTime(uint32 ms) { _startTime += ms; }
     134
     135        /**
     136         * Returns if the video is finished or not
     137         */
     138        virtual bool endOfVideo() const;
     139
     140        /**
     141         * Set the current palette to the system palette
     142         */
     143        void setSystemPalette();
     144
     145        /**
     146         * Return the time until the next frame (in ms)
     147         */
     148        virtual uint32 getTimeToNextFrame() const = 0;
     149
     150protected:
     151        /**
     152         * Resets _curFrame and _startTime. Should be called from every close() function.
     153         */
     154        void reset();
     155
     156        int32 _curFrame;
     157        uint32 _startTime;
     158};
     159
     160/**
     161 * A VideoDecoder wrapper that implements getTimeToNextFrame() based on getFrameRate().
     162 */
     163class FixedRateVideoDecoder : public VideoDecoder {
     164public:
     165        FixedRateVideoDecoder() {}
     166        virtual ~FixedRateVideoDecoder() {}
     167
     168        uint32 getTimeToNextFrame() const;
     169
     170protected:
     171        /**
     172         * Return the frame rate in frames per second
     173         * This returns a Rational because videos can have rates that are not integers and
     174         * there are some videos with frame rates < 1.
     175         */
     176        virtual Common::Rational getFrameRate() const = 0;
     177
     178private:
     179        uint32 getFrameBeginTime(uint32 frame) const;
     180};
     181
     182} // End of namespace Graphics
     183
     184#endif
  • graphics/video/dxa_decoder.cpp

     
    3939
    4040DXADecoder::DXADecoder() {
    4141        _fileStream = 0;
     42        _surface = 0;
     43        _dirtyPalette = false;
    4244
    4345        _frameBuffer1 = 0;
    4446        _frameBuffer2 = 0;
    4547        _scaledBuffer = 0;
    46         _videoFrameBuffer = 0;
    4748
    4849        _inBuffer = 0;
    4950        _inBufferSize = 0;
     
    5152        _decompBuffer = 0;
    5253        _decompBufferSize = 0;
    5354
    54         _videoInfo.width = 0;
    55         _videoInfo.height = 0;
     55        _width = 0;
     56        _height = 0;
    5657
    5758        _frameSize = 0;
    58         _videoInfo.frameCount = 0;
    59         _videoInfo.currentFrame = -1;
    60         _videoInfo.frameRate = 0;
    61         _videoInfo.frameDelay = 0;
     59        _frameCount = 0;
     60        _frameRate = 0;
    6261
    6362        _scaleMode = S_NONE;
    6463}
    6564
    6665DXADecoder::~DXADecoder() {
    67         closeFile();
     66        close();
    6867}
    6968
    70 bool DXADecoder::loadFile(const char *fileName) {
    71         uint32 tag;
    72         int32 frameRate;
     69bool DXADecoder::load(Common::SeekableReadStream &stream) {
     70        close();
    7371
    74         closeFile();
     72        _fileStream = &stream;
    7573
    76         _fileStream = SearchMan.createReadStreamForMember(fileName);
    77         if (!_fileStream)
    78                 return false;
    79 
    80         tag = _fileStream->readUint32BE();
     74        uint32 tag = _fileStream->readUint32BE();
    8175        assert(tag == MKID_BE('DEXA'));
    8276
    8377        uint8 flags = _fileStream->readByte();
    84         _videoInfo.frameCount = _fileStream->readUint16BE();
    85         frameRate = _fileStream->readSint32BE();
     78        _frameCount = _fileStream->readUint16BE();
     79        int32 frameRate = _fileStream->readSint32BE();
    8680
    87         if (frameRate > 0) {
    88                 _videoInfo.frameRate = 1000 / frameRate;
    89                 _videoInfo.frameDelay = frameRate * 100;
    90         } else if (frameRate < 0) {
    91                 _videoInfo.frameRate = 100000 / (-frameRate);
    92                 _videoInfo.frameDelay = -frameRate;
    93         } else {
    94                 _videoInfo.frameRate = 10;
    95                 _videoInfo.frameDelay = 10000;
    96         }
     81        if (frameRate > 0)
     82                _frameRate = 1000 / frameRate;
     83        else if (frameRate < 0)
     84                _frameRate = 100000 / (-frameRate);
     85        else
     86                _frameRate = 10;
    9787
    98         _videoInfo.width = _fileStream->readUint16BE();
    99         _videoInfo.height = _fileStream->readUint16BE();
     88        _width = _fileStream->readUint16BE();
     89        _height = _fileStream->readUint16BE();
    10090
    10191        if (flags & 0x80) {
    10292                _scaleMode = S_INTERLACED;
    103                 _curHeight = _videoInfo.height / 2;
     93                _curHeight = _height / 2;
    10494        } else if (flags & 0x40) {
    10595                _scaleMode = S_DOUBLE;
    106                 _curHeight = _videoInfo.height / 2;
     96                _curHeight = _height / 2;
    10797        } else {
    10898                _scaleMode = S_NONE;
    109                 _curHeight = _videoInfo.height;
     99                _curHeight = _height;
    110100        }
    111101
    112         debug(2, "flags 0x0%x framesCount %d width %d height %d rate %d ticks %d", flags, getFrameCount(), getWidth(), getHeight(), getFrameRate(), getFrameDelay());
     102        _surface = new Graphics::Surface();
     103        _surface->bytesPerPixel = 1;
    113104
    114         _frameSize = _videoInfo.width * _videoInfo.height;
     105        debug(2, "flags 0x0%x framesCount %d width %d height %d rate %d", flags, getFrameCount(), getWidth(), getHeight(), getFrameRate().toInt());
     106
     107        _frameSize = _width * _height;
    115108        _decompBufferSize = _frameSize;
    116109        _frameBuffer1 = (uint8 *)malloc(_frameSize);
    117110        memset(_frameBuffer1, 0, _frameSize);
     
    135128
    136129                do {
    137130                        tag = _fileStream->readUint32BE();
    138                         if (tag != 0) {
     131
     132                        if (tag != 0)
    139133                                size = _fileStream->readUint32BE();
    140                         }
     134
    141135                        switch (tag) {
    142136                                case 0: // No more tags
    143137                                        break;
     
    159153        // Read the sound header
    160154        _soundTag = _fileStream->readUint32BE();
    161155
    162         _videoInfo.currentFrame = -1;
    163 
    164         _videoInfo.firstframeOffset = _fileStream->pos();
    165 
    166156        return true;
    167157}
    168158
    169 void DXADecoder::closeFile() {
     159void DXADecoder::close() {
    170160        if (!_fileStream)
    171161                return;
    172162
    173163        delete _fileStream;
    174164        _fileStream = 0;
    175165
     166        delete _surface;
     167        _surface = 0;
     168
    176169        free(_frameBuffer1);
    177170        free(_frameBuffer2);
    178171        free(_scaledBuffer);
     
    181174
    182175        _inBuffer = 0;
    183176        _decompBuffer = 0;
     177
     178        reset();
    184179}
    185180
    186181void DXADecoder::decodeZlib(byte *data, int size, int totalSize) {
     
    208203
    209204        memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
    210205
    211         for (uint32 by = 0; by < _videoInfo.height; by += BLOCKH) {
    212                 for (uint32 bx = 0; bx < _videoInfo.width; bx += BLOCKW) {
     206        for (uint32 by = 0; by < _height; by += BLOCKH) {
     207                for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
    213208                        byte type = *dat++;
    214                         byte *b2 = _frameBuffer1 + bx + by * _videoInfo.width;
     209                        byte *b2 = _frameBuffer1 + bx + by * _width;
    215210
    216211                        switch (type) {
    217212                        case 0:
     
    243238                                                }
    244239                                                diffMap <<= 1;
    245240                                        }
    246                                         b2 += _videoInfo.width;
     241                                        b2 += _width;
    247242                                }
    248243                                break;
    249244                        }
     
    254249                                        for (int xc = 0; xc < BLOCKW; xc++) {
    255250                                                b2[xc] = color;
    256251                                        }
    257                                         b2 += _videoInfo.width;
     252                                        b2 += _width;
    258253                                }
    259254                                break;
    260255                        }
     
    263258                                        for (int xc = 0; xc < BLOCKW; xc++) {
    264259                                                b2[xc] = *dat++;
    265260                                        }
    266                                         b2 += _videoInfo.width;
     261                                        b2 += _width;
    267262                                }
    268263                                break;
    269264                        }
     
    275270                                int my = mbyte & 0x07;
    276271                                if (mbyte & 0x08)
    277272                                        my = -my;
    278                                 byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _videoInfo.width;
     273                                byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _width;
    279274                                for (int yc = 0; yc < BLOCKH; yc++) {
    280275                                        memcpy(b2, b1, BLOCKW);
    281                                         b1 += _videoInfo.width;
    282                                         b2 += _videoInfo.width;
     276                                        b1 += _width;
     277                                        b2 += _width;
    283278                                }
    284279                                break;
    285280                        }
     
    309304
    310305        memcpy(_frameBuffer2, _frameBuffer1, _frameSize);
    311306
    312         int codeSize = _videoInfo.width * _curHeight / 16;
     307        int codeSize = _width * _curHeight / 16;
    313308        int dataSize, motSize, maskSize;
    314309
    315310        dataSize = READ_BE_UINT32(&_decompBuffer[0]);
     
    322317        maskBuf = &motBuf[motSize];
    323318
    324319        for (uint32 by = 0; by < _curHeight; by += BLOCKH) {
    325                 for (uint32 bx = 0; bx < _videoInfo.width; bx += BLOCKW) {
     320                for (uint32 bx = 0; bx < _width; bx += BLOCKW) {
    326321                        uint8 type = *codeBuf++;
    327                         uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _videoInfo.width;
     322                        uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _width;
    328323
    329324                        switch (type) {
    330325                        case 0:
     
    341336                                                }
    342337                                                diffMap <<= 1;
    343338                                        }
    344                                         b2 += _videoInfo.width;
     339                                        b2 += _width;
    345340                                }
    346341                                break;
    347342                        }
     
    352347                                        for (int xc = 0; xc < BLOCKW; xc++) {
    353348                                                b2[xc] = color;
    354349                                        }
    355                                         b2 += _videoInfo.width;
     350                                        b2 += _width;
    356351                                }
    357352                                break;
    358353                        }
     
    361356                                        for (int xc = 0; xc < BLOCKW; xc++) {
    362357                                                b2[xc] = *dataBuf++;
    363358                                        }
    364                                         b2 += _videoInfo.width;
     359                                        b2 += _width;
    365360                                }
    366361                                break;
    367362                        }
     
    375370                                if (mbyte & 0x08)
    376371                                        my = -my;
    377372
    378                                 uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _videoInfo.width;
     373                                uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _width;
    379374                                for (int yc = 0; yc < BLOCKH; yc++) {
    380375                                        memcpy(b2, b1, BLOCKW);
    381                                         b1 += _videoInfo.width;
    382                                         b2 += _videoInfo.width;
     376                                        b1 += _width;
     377                                        b2 += _width;
    383378                                }
    384379                                break;
    385380                        }
     
    391386
    392387                                for (int subBlock = 0; subBlock < 4; subBlock++) {
    393388                                        int sx = bx + subX[subBlock], sy = by + subY[subBlock];
    394                                         b2 = (uint8*)_frameBuffer1 + sx + sy * _videoInfo.width;
     389                                        b2 = (uint8*)_frameBuffer1 + sx + sy * _width;
    395390                                        switch (subMask & 0xC0) {
    396391                                        // 00: skip
    397392                                        case 0x00:
     
    403398                                                        for (int xc = 0; xc < BLOCKW / 2; xc++) {
    404399                                                                b2[xc] = subColor;
    405400                                                        }
    406                                                         b2 += _videoInfo.width;
     401                                                        b2 += _width;
    407402                                                }
    408403                                                break;
    409404                                        }
     
    419414                                                if (mbyte & 0x08)
    420415                                                        my = -my;
    421416
    422                                                 uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _videoInfo.width;
     417                                                uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _width;
    423418                                                for (int yc = 0; yc < BLOCKH / 2; yc++) {
    424419                                                        memcpy(b2, b1, BLOCKW / 2);
    425                                                         b1 += _videoInfo.width;
    426                                                         b2 += _videoInfo.width;
     420                                                        b1 += _width;
     421                                                        b2 += _width;
    427422                                                }
    428423                                                break;
    429424                                        }
     
    433428                                                        for (int xc = 0; xc < BLOCKW / 2; xc++) {
    434429                                                                b2[xc] = *dataBuf++;
    435430                                                        }
    436                                                         b2 += _videoInfo.width;
     431                                                        b2 += _width;
    437432                                                }
    438433                                                break;
    439434                                        }
     
    458453                                                        b2[xc] = pixels[code & 1];
    459454                                                        code >>= 1;
    460455                                                }
    461                                                 b2 += _videoInfo.width;
     456                                                b2 += _width;
    462457                                        }
    463458                                } else {
    464459                                        uint32 code = READ_BE_UINT32(maskBuf);
     
    468463                                                        b2[xc] = pixels[code & 3];
    469464                                                        code >>= 2;
    470465                                                }
    471                                                 b2 += _videoInfo.width;
     466                                                b2 += _width;
    472467                                        }
    473468                                }
    474469                                break;
     
    481476#endif
    482477}
    483478
    484 bool DXADecoder::decodeNextFrame() {
    485         uint32 tag;
    486 
    487         _videoInfo.currentFrame++;
    488 
    489         if (_videoInfo.currentFrame == 0)
    490                 _videoInfo.startTime = g_system->getMillis();
    491 
    492         tag = _fileStream->readUint32BE();
     479Surface *DXADecoder::decodeNextFrame() {
     480        uint32 tag = _fileStream->readUint32BE();
    493481        if (tag == MKID_BE('CMAP')) {
    494                 byte rgb[768];
    495 
    496                 _fileStream->read(rgb, ARRAYSIZE(rgb));
    497                 setPalette(rgb);
     482                _fileStream->read(_palette, 256 * 3);
     483                _dirtyPalette = true;
    498484        }
    499485
    500486        tag = _fileStream->readUint32BE();
     
    531517
    532518                if (type == 3) {
    533519                        for (uint32 j = 0; j < _curHeight; ++j) {
    534                                 for (uint32 i = 0; i < _videoInfo.width; ++i) {
    535                                         const int offs = j * _videoInfo.width + i;
     520                                for (uint32 i = 0; i < _width; ++i) {
     521                                        const int offs = j * _width + i;
    536522                                        _frameBuffer1[offs] ^= _frameBuffer2[offs];
    537523                                }
    538524                        }
     
    542528        switch (_scaleMode) {
    543529        case S_INTERLACED:
    544530                for (int cy = 0; cy < _curHeight; cy++) {
    545                         memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
    546                         memset(&_scaledBuffer[((2 * cy) + 1) * _videoInfo.width], 0, _videoInfo.width);
     531                        memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
     532                        memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width);
    547533                }
    548                 _videoFrameBuffer = _scaledBuffer;
     534                _surface->pixels = _scaledBuffer;
    549535                break;
    550536        case S_DOUBLE:
    551537                for (int cy = 0; cy < _curHeight; cy++) {
    552                         memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
    553                         memcpy(&_scaledBuffer[((2 * cy) + 1) * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
     538                        memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width);
     539                        memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width);
    554540                }
    555                 _videoFrameBuffer = _scaledBuffer;
     541                _surface->pixels = _scaledBuffer;
    556542                break;
    557543        case S_NONE:
    558                 _videoFrameBuffer = _frameBuffer1;
     544                _surface->pixels = _frameBuffer1;
    559545                break;
    560546        }
    561547
    562         return !endOfVideo();
     548        // Copy in the relevant info to the Surface
     549        _surface->w = getWidth();
     550        _surface->h = getHeight();
     551        _surface->pitch = getWidth();
     552
     553        _curFrame++;
     554
     555        if (_curFrame == 0)
     556                _startTime = g_system->getMillis();
     557
     558        return _surface;
    563559}
    564560
    565561} // End of namespace Graphics
  • graphics/video/flic_decoder.cpp

     
    3434FlicDecoder::FlicDecoder() {
    3535        _paletteChanged = false;
    3636        _fileStream = 0;
    37         _videoFrameBuffer = 0;
    38         memset(&_videoInfo, 0, sizeof(_videoInfo));
     37        _surface = 0;
    3938}
    4039
    4140FlicDecoder::~FlicDecoder() {
    42         closeFile();
     41        close();
    4342}
    4443
    45 bool FlicDecoder::loadFile(const char *fileName) {
    46         closeFile();
     44bool FlicDecoder::load(Common::SeekableReadStream &stream) {
     45        close();
    4746
    48         _fileStream = SearchMan.createReadStreamForMember(fileName);
    49         if (!_fileStream)
    50                 return false;
     47        _fileStream = &stream;
    5148
    5249        /* uint32 frameSize = */ _fileStream->readUint32LE();
    5350        uint16 frameType = _fileStream->readUint16LE();
     
    6057                return false;
    6158        }
    6259
    63         _videoInfo.frameCount = _fileStream->readUint16LE();
    64         _videoInfo.width = _fileStream->readUint16LE();
    65         _videoInfo.height = _fileStream->readUint16LE();
     60       
     61        _frameCount = _fileStream->readUint16LE();
     62        uint16 width = _fileStream->readUint16LE();
     63        uint16 height = _fileStream->readUint16LE();
    6664        uint16 colorDepth = _fileStream->readUint16LE();
    6765        if (colorDepth != 8) {
    6866                warning("FlicDecoder::FlicDecoder(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", frameType);
     
    7068                _fileStream = 0;
    7169                return false;
    7270        }
     71
    7372        _fileStream->readUint16LE();    // flags
    7473        // Note: The normal delay is a 32-bit integer (dword), whereas the overriden delay is a 16-bit integer (word)
    7574        // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
    76         _videoInfo.frameDelay = 100 * _fileStream->readUint32LE();
    77         _videoInfo.frameRate = 100 * 1000 / _videoInfo.frameDelay;
     75        uint32 frameDelay = 100 * _fileStream->readUint32LE();
     76        _frameRate = 100 * 1000 / frameDelay;
    7877
    7978        _fileStream->seek(80);
    8079        _offsetFrame1 = _fileStream->readUint32LE();
    8180        _offsetFrame2 = _fileStream->readUint32LE();
    8281
    83         _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height];
     82        _surface = new Graphics::Surface();
     83        _surface->create(width, height, 1);
    8484        _palette = (byte *)malloc(3 * 256);
    8585        memset(_palette, 0, 3 * 256);
    8686        _paletteChanged = false;
    8787
    8888        // Seek to the first frame
    89         _videoInfo.currentFrame = -1;
    9089        _fileStream->seek(_offsetFrame1);
    9190        return true;
    9291}
    9392
    94 void FlicDecoder::closeFile() {
     93void FlicDecoder::close() {
    9594        if (!_fileStream)
    9695                return;
    9796
    9897        delete _fileStream;
    9998        _fileStream = 0;
    10099
    101         delete[] _videoFrameBuffer;
    102         _videoFrameBuffer = 0;
     100        _surface->free();
     101        delete _surface;
     102        _surface = 0;
    103103
    104104        free(_palette);
     105        _dirtyRects.clear();
    105106
    106         _dirtyRects.clear();
     107        reset();
    107108}
    108109
    109110void FlicDecoder::decodeByteRun(uint8 *data) {
    110         byte *ptr = (uint8 *)_videoFrameBuffer;
    111         while ((uint32)(ptr - _videoFrameBuffer) < (_videoInfo.width * _videoInfo.height)) {
     111        byte *ptr = (byte *)_surface->pixels;
     112        while ((int32)(ptr - (byte *)_surface->pixels) < (getWidth() * getHeight())) {
    112113                int chunks = *data++;
    113114                while (chunks--) {
    114115                        int count = (int8)*data++;
     
    125126
    126127        // Redraw
    127128        _dirtyRects.clear();
    128         _dirtyRects.push_back(Common::Rect(0, 0, _videoInfo.width, _videoInfo.height));
     129        _dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight()));
    129130}
    130131
    131132#define OP_PACKETCOUNT   0
     
    152153                        case OP_UNDEFINED:
    153154                                break;
    154155                        case OP_LASTPIXEL:
    155                                 _videoFrameBuffer[currentLine * _videoInfo.width + _videoInfo.width - 1] = (opcode & 0xFF);
    156                                 _dirtyRects.push_back(Common::Rect(_videoInfo.width - 1, currentLine, _videoInfo.width, currentLine + 1));
     156                                *((byte *)_surface->pixels + currentLine * getWidth() + getWidth() - 1) = (opcode & 0xFF);
     157                                _dirtyRects.push_back(Common::Rect(getWidth() - 1, currentLine, getWidth(), currentLine + 1));
    157158                                break;
    158159                        case OP_LINESKIPCOUNT:
    159160                                currentLine += -(int16)opcode;
     
    168169                        column += *data++;
    169170                        int rleCount = (int8)*data++;
    170171                        if (rleCount > 0) {
    171                                 memcpy(_videoFrameBuffer + (currentLine * _videoInfo.width) + column, data, rleCount * 2);
     172                                memcpy((byte *)_surface->pixels + (currentLine * getWidth()) + column, data, rleCount * 2);
    172173                                data += rleCount * 2;
    173174                                _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1));
    174175                        } else if (rleCount < 0) {
    175176                                rleCount = -rleCount;
    176177                                uint16 dataWord = READ_UINT16(data); data += 2;
    177178                                for (int i = 0; i < rleCount; ++i) {
    178                                         WRITE_UINT16(_videoFrameBuffer + currentLine * _videoInfo.width + column + i * 2, dataWord);
     179                                        WRITE_UINT16((byte *)_surface->pixels + currentLine * getWidth() + column + i * 2, dataWord);
    179180                                }
    180181                                _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1));
    181182                        } else { // End of cutscene ?
     
    194195#define PSTAMP     18
    195196#define FRAME_TYPE 0xF1FA
    196197
    197 bool FlicDecoder::decodeNextFrame() {
     198Surface *FlicDecoder::decodeNextFrame() {
    198199        // Read chunk
    199200        uint32 frameSize = _fileStream->readUint32LE();
    200201        uint16 frameType = _fileStream->readUint16LE();
    201202        uint16 chunkCount = 0;
    202203
    203204        switch (frameType) {
    204         case FRAME_TYPE: {
    205                 chunkCount = _fileStream->readUint16LE();
    206                 // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
    207                 // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
    208                 uint16 newFrameDelay = _fileStream->readUint16LE();     // "speed", in milliseconds
    209                 if (newFrameDelay > 0) {
    210                         _videoInfo.frameDelay = 100 * newFrameDelay;
    211                         _videoInfo.frameRate = 100 * 1000 / _videoInfo.frameDelay;
    212                 }
    213                 _fileStream->readUint16LE();    // reserved, always 0
    214                 uint16 newWidth = _fileStream->readUint16LE();
    215                 uint16 newHeight = _fileStream->readUint16LE();
    216                 if (newWidth > 0)
    217                         _videoInfo.width = newWidth;
    218                 if (newHeight > 0)
    219                         _videoInfo.height = newHeight;
     205        case FRAME_TYPE:
     206                {
     207                        // FIXME: FLIC should be switched over to a variable frame rate VideoDecoder to handle
     208                        // this properly.
    220209
    221                 _videoInfo.currentFrame++;
     210                        chunkCount = _fileStream->readUint16LE();
     211                        // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
     212                        // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
     213                        uint16 newFrameDelay = _fileStream->readUint16LE();     // "speed", in milliseconds
     214                        if (newFrameDelay > 0)
     215                                _frameRate = 1000 / newFrameDelay;
    222216
    223                 if (_videoInfo.currentFrame == 0)
    224                         _videoInfo.startTime = g_system->getMillis();
     217                        _fileStream->readUint16LE();    // reserved, always 0
     218                        uint16 newWidth = _fileStream->readUint16LE();
     219                        uint16 newHeight = _fileStream->readUint16LE();
     220
     221                        if ((newWidth != 0) && (newHeight != 0)) {
     222                                if (newWidth == 0)
     223                                        newWidth = _surface->w;
     224                                if (newHeight == 0)
     225                                        newHeight = _surface->h;
     226
     227                                _surface->free();
     228                                delete _surface;
     229                                _surface = new Graphics::Surface();
     230                                _surface->create(newWidth, newHeight, 1);
     231                        }
    225232                }
    226233                break;
    227234        default:
     
    239246                        switch (frameType) {
    240247                        case FLI_SETPAL:
    241248                                unpackPalette(data);
    242                                 setPalette(_palette);
    243249                                _paletteChanged = true;
    244250                                break;
    245251                        case FLI_SS2:
     
    259265                        delete[] data;
    260266                }
    261267        }
     268       
     269        _curFrame++;
    262270
     271        if (_curFrame == 0)
     272                _startTime = g_system->getMillis();
     273
    263274        // If we just processed the ring frame, set the next frame
    264         if (_videoInfo.currentFrame == (int32)_videoInfo.frameCount + 1) {
    265                 _videoInfo.currentFrame = 1;
     275        if (_curFrame == (int32)_frameCount) {
     276                _curFrame = 0;
    266277                _fileStream->seek(_offsetFrame2);
    267278        }
    268279
    269         return !endOfVideo();
     280        return _surface;
    270281}
    271282
    272283void FlicDecoder::reset() {
    273         _videoInfo.currentFrame = 0;
    274         _fileStream->seek(_offsetFrame1);
     284        VideoDecoder::reset();
     285        if (_fileStream)
     286                _fileStream->seek(_offsetFrame1);
    275287}
    276288
    277289void FlicDecoder::unpackPalette(uint8 *data) {
     
    303315        for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
    304316                for (int y = (*it).top; y < (*it).bottom; ++y) {
    305317                        const int x = (*it).left;
    306                         memcpy(dst + y * pitch + x, _videoFrameBuffer + y * _videoInfo.width + x, (*it).right - x);
     318                        memcpy(dst + y * pitch + x, (byte *)_surface->pixels + y * getWidth() + x, (*it).right - x);
    307319                }
    308320        }
    309321        _dirtyRects.clear();
  • graphics/video/avi_decoder.cpp

     
    2323 *
    2424 */
    2525
    26 #include "common/archive.h"
    2726#include "common/endian.h"
    2827#include "common/file.h"
    2928#include "common/stream.h"
     
    4948        _audStream = NULL;
    5049        _fileStream = NULL;
    5150        _audHandle = new Audio::SoundHandle();
     51        _dirtyPalette = false;
    5252        memset(_palette, 0, sizeof(_palette));
    5353        memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT));
    5454        memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER));
     
    5858}
    5959
    6060AviDecoder::~AviDecoder() {
    61         closeFile();
     61        close();
    6262        delete _audHandle;
    6363}
    6464
     
    190190                                /*_palette[i * 4 + 3] = */_fileStream->readByte();
    191191                        }
    192192
    193                         setPalette(_palette);
     193                        _dirtyPalette = true;
    194194                }
    195195        } else if (sHeader.streamType == ID_AUDS) {
    196196                _audsHeader = sHeader;
     
    204204        }
    205205}
    206206
    207 bool AviDecoder::loadFile(const char *fileName) {
    208         closeFile();
     207bool AviDecoder::load(Common::SeekableReadStream &stream) {
     208        close();
    209209
    210         _fileStream = SearchMan.createReadStreamForMember(fileName);
    211         if (!_fileStream)
    212                 return false;
    213 
     210        _fileStream = &stream;
    214211        _decodedHeader = false;
    215         // Seek to the first frame
    216         _videoInfo.currentFrame = -1;
    217212
    218213        // Read chunks until we have decoded the header
    219214        while (!_decodedHeader)
    220215                runHandle(_fileStream->readUint32BE());
    221216
    222         _videoFrameBuffer = new byte[_header.width * _header.height];
    223         memset(_videoFrameBuffer, 0, _header.width * _header.height);
    224 
    225217        uint32 nextTag = _fileStream->readUint32BE();
    226218
    227219        // Throw out any JUNK section
     
    247239                _mixer->playStream(_soundType, _audHandle, _audStream);
    248240
    249241        debug (0, "Frames = %d, Dimensions = %d x %d", _header.totalFrames, _header.width, _header.height);
    250         debug (0, "Frame Rate = %d", getFrameRate());
     242        debug (0, "Frame Rate = %d", _vidsHeader.rate / _vidsHeader.scale);
    251243        if ((_audsHeader.scale != 0) && (_header.flags & AVIF_ISINTERLEAVED))
    252244                debug (0, "Sound Rate = %d", AUDIO_RATE);
    253245        debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler));
    254246
    255         _videoInfo.firstframeOffset = _fileStream->pos();
    256         _videoInfo.width = _header.width;
    257         _videoInfo.height = _header.height;
    258         _videoInfo.frameCount = _header.totalFrames;
    259         // Our frameDelay is calculated in 1/100 ms, so we convert it here
    260         _videoInfo.frameDelay = _header.microSecondsPerFrame / 10;
    261 
    262247        if (!_videoCodec)
    263248                return false;
    264249
    265250        return true;
    266251}
    267252
    268 void AviDecoder::closeFile() {
     253void AviDecoder::close() {
    269254        if (!_fileStream)
    270255                return;
    271256
    272257        delete _fileStream;
    273258        _fileStream = 0;
    274259
    275         delete[] _videoFrameBuffer;
    276         _videoFrameBuffer = 0;
    277 
    278260        // Deinitialize sound
    279261        _mixer->stopHandle(*_audHandle);
    280262        _audStream = 0;
     
    293275        memset(&_vidsHeader, 0, sizeof(AVIStreamHeader));
    294276        memset(&_audsHeader, 0, sizeof(AVIStreamHeader));
    295277        memset(&_ixInfo, 0, sizeof(AVIOLDINDEX));
     278
     279        reset();
    296280}
    297281
    298 Surface *AviDecoder::getNextFrame() {
     282uint32 AviDecoder::getElapsedTime() const {
     283        if (_audStream)
     284                return _mixer->getSoundElapsedTime(*_audHandle);
     285
     286        return VideoDecoder::getElapsedTime();
     287}
     288
     289Surface *AviDecoder::decodeNextFrame() {
    299290        uint32 nextTag = _fileStream->readUint32BE();
    300291
    301292        if (_fileStream->eos())
    302293                return NULL;
    303294
     295        if (_curFrame == -1)
     296                _startTime = g_system->getMillis();
     297
    304298        if (nextTag == ID_LIST) {
    305299                // A list of audio/video chunks
    306300                uint32 listSize = _fileStream->readUint32LE() - 4;
     
    312306                // Decode chunks in the list and see if we get a frame
    313307                Surface *frame = NULL;
    314308                while (_fileStream->pos() < startPos + (int32)listSize) {
    315                         Surface *temp = getNextFrame();
     309                        Surface *temp = decodeNextFrame();
    316310                        if (temp)
    317311                                frame = temp;
    318312                }
     
    335329        } else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' ||
    336330                   getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32') {
    337331                // Compressed Frame
    338                 _videoInfo.currentFrame++;
     332                _curFrame++;
    339333                uint32 chunkSize = _fileStream->readUint32LE();
    340334
    341335                if (chunkSize == 0) // Keep last frame on screen
     
    364358                        _fileStream->readByte(); // Flags that don't serve us any purpose
    365359                }
    366360
    367                 setPalette(_palette);
     361                _dirtyPalette = true;
    368362
    369363                // No alignment necessary. It's always even.
    370364        } else if (nextTag == ID_JUNK) {
     
    372366        } else if (nextTag == ID_IDX1) {
    373367                runHandle(ID_IDX1);
    374368        } else
    375                 error ("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());
     369                error("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());
    376370
    377371        return NULL;
    378372}
    379373
    380 bool AviDecoder::decodeNextFrame() {
    381         Surface *surface = NULL;
    382 
    383         int32 curFrame = _videoInfo.currentFrame;
    384 
    385         while (!surface && !endOfVideo() && !_fileStream->eos())
    386                 surface = getNextFrame();
    387 
    388         if (curFrame == _videoInfo.currentFrame) {
    389                 warning("No video frame found");
    390                 _videoInfo.currentFrame++;
    391         }
    392 
    393         if (surface)
    394                 memcpy(_videoFrameBuffer, surface->pixels, _header.width * _header.height);
    395 
    396         if (_videoInfo.currentFrame == 0)
    397                 _videoInfo.startTime = g_system->getMillis();
    398 
    399         return !endOfVideo();
    400 }
    401 
    402 int32 AviDecoder::getAudioLag() {
    403         if (!_fileStream)
    404                 return 0;
    405 
    406         int32 frameDelay = getFrameDelay();
    407         int32 videoTime = (_videoInfo.currentFrame + 1) * frameDelay;
    408         int32 audioTime;
    409 
    410         if (!_audStream) {
    411                 /* No audio.
    412                    Calculate the lag by how much time has gone by since the first frame
    413                    and how much time *should* have passed.
    414                 */
    415 
    416                 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
    417         } else {
    418                 const Audio::Timestamp ts = _mixer->getElapsedTime(*_audHandle);
    419                 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
    420         }
    421 
    422         return videoTime - audioTime;
    423 }
    424 
    425374Codec *AviDecoder::createCodec() {
    426375        switch (_vidsHeader.streamHandler) {
    427376                case ID_CRAM:
     
    437386        return NULL;
    438387}
    439388
    440 Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
     389PixelFormat AviDecoder::getPixelFormat() const {
     390        assert(_videoCodec);
     391        return _videoCodec->getPixelFormat();
     392}
    441393
    442         if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) {
     394Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
     395        if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM)
    443396                return Audio::makeQueuingAudioStream(AUDIO_RATE, false);
    444         }
    445397
    446398        if (_wvInfo.tag != 0) // No sound
    447399                warning ("Unsupported AVI audio format %d", _wvInfo.tag);
  • graphics/video/dxa_decoder.h

     
    2626#ifndef GRAPHICS_VIDEO_DXA_PLAYER_H
    2727#define GRAPHICS_VIDEO_DXA_PLAYER_H
    2828
    29 #include "graphics/video/video_player.h"
     29#include "graphics/video/video_decoder.h"
    3030
    3131namespace Graphics {
    3232
     
    3838 *  - sword1
    3939 *  - sword2
    4040 */
    41 class DXADecoder : public VideoDecoder {
     41class DXADecoder : public FixedRateVideoDecoder {
    4242public:
    4343        DXADecoder();
    4444        virtual ~DXADecoder();
    4545
    46         /**
    47          * Load a DXA encoded video file
    48          * @param filename      the filename to load
    49          */
    50         bool loadFile(const char *fileName);
     46        bool load(Common::SeekableReadStream &stream);
     47        void close();
     48       
     49        bool isVideoLoaded() const { return _fileStream != 0; }
     50        uint16 getWidth() const { return _width; }
     51        uint16 getHeight() const { return _height; }
     52        uint32 getFrameCount() const { return _frameCount; }
     53        Surface *decodeNextFrame();
     54        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
     55        byte *getPalette() { _dirtyPalette = false; return _palette; }
     56        bool hasDirtyPalette() const { return _dirtyPalette; }
    5157
    5258        /**
    53          * Close a DXA encoded video file
    54          */
    55         void closeFile();
    56 
    57         bool decodeNextFrame();
    58 
    59         /**
    6059         * Get the sound chunk tag of the loaded DXA file
    6160         */
    6261        uint32 getSoundTag() { return _soundTag; }
    6362
     63protected:
     64        Common::Rational getFrameRate() const { return _frameRate; }
     65
     66        Common::SeekableReadStream *_fileStream;
     67
    6468private:
    6569        void decodeZlib(byte *data, int size, int totalSize);
    6670        void decode12(int size);
     
    7276                S_DOUBLE
    7377        };
    7478
     79        Graphics::Surface *_surface;
     80        byte _palette[256 * 3];
     81        bool _dirtyPalette;
     82
    7583        byte *_frameBuffer1;
    7684        byte *_frameBuffer2;
    7785        byte *_scaledBuffer;
     
    8391        uint32 _frameSize;
    8492        ScaleMode _scaleMode;
    8593        uint32 _soundTag;
     94        uint16 _width, _height;
     95        uint32 _frameRate;
     96        uint32 _frameCount;
    8697};
    8798
    8899} // End of namespace Graphics
  • graphics/video/flic_decoder.h

     
    2323 *
    2424 */
    2525
    26 #ifndef GRAPHICS_VIDEO_FlicDecoder_H
    27 #define GRAPHICS_VIDEO_FlicDecoder_H
     26#ifndef GRAPHICS_VIDEO_FLICDECODER_H
     27#define GRAPHICS_VIDEO_FLICDECODER_H
    2828
    29 #include "graphics/video/video_player.h"
     29#include "graphics/video/video_decoder.h"
    3030#include "common/list.h"
    3131#include "common/rect.h"
    3232
     
    4242 * Video decoder used in engines:
    4343 *  - tucker
    4444 */
    45 class FlicDecoder : public VideoDecoder {
     45class FlicDecoder : public FixedRateVideoDecoder {
    4646public:
    4747        FlicDecoder();
    4848        virtual ~FlicDecoder();
    4949
    5050        /**
    51          * Load a FLIC encoded video file
    52          * @param filename      the filename to load
     51         * Load a video file
     52         * @param stream  the stream to load
    5353         */
    54         bool loadFile(const char *fileName);
     54        bool load(Common::SeekableReadStream &stream);
     55        void close();
    5556
    5657        /**
    57          * Close a FLIC encoded video file
     58         * Decode the next frame and return the frame's surface
     59         * @note the return surface should *not* be freed
     60         * @note this may return 0, in which case the last frame should be kept on screen
    5861         */
    59         void closeFile();
     62        Surface *decodeNextFrame();
    6063
    61         /**
    62          * Decode the next frame
    63          */
    64         bool decodeNextFrame();
     64        bool isVideoLoaded() const { return _fileStream != 0; }
     65        uint16 getWidth() const { return _surface->w; }
     66        uint16 getHeight() const { return _surface->h; }
     67        uint32 getFrameCount() const { return _frameCount; }
     68        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
    6569
    6670        const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; }
    6771        void clearDirtyRects() { _dirtyRects.clear(); }
    6872        void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
    6973
    70         const byte *getPalette() { _paletteChanged = false; return _palette; }
    71         bool paletteChanged() { return _paletteChanged; }
     74        byte *getPalette() { _paletteChanged = false; return _palette; }
     75        bool hasDirtyPalette() { return _paletteChanged; }
    7276        void reset();
    7377
     78protected:
     79        Common::Rational getFrameRate() const { return _frameRate; }
     80
    7481private:
    7582        uint16 _offsetFrame1;
    7683        uint16 _offsetFrame2;
     
    8188        void decodeDeltaFLC(uint8 *data);
    8289        void unpackPalette(uint8 *mem);
    8390
     91        Common::SeekableReadStream *_fileStream;
     92        Surface *_surface;
     93        uint32 _frameCount;
     94        uint32 _frameRate;
     95
    8496        Common::List<Common::Rect> _dirtyRects;
    85 
    8697};
    8798
    8899} // End of namespace Graphics
  • graphics/video/avi_decoder.h

     
    2626#ifndef GRAPHICS_AVI_PLAYER_H
    2727#define GRAPHICS_AVI_PLAYER_H
    2828
    29 #include "graphics/video/video_player.h"
     29#include "graphics/video/video_decoder.h"
    3030#include "graphics/video/codecs/codec.h"
    3131#include "sound/audiostream.h"
    3232#include "sound/mixer.h"
     
    172172        Common::Rect frame;
    173173};
    174174
    175 class AviDecoder : public VideoDecoder {
     175class AviDecoder : public FixedRateVideoDecoder {
    176176public:
    177177        AviDecoder(Audio::Mixer *mixer,
    178178                        Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType);
    179179        virtual ~AviDecoder();
    180180
    181         /**
    182          * Load an AVI video file
    183          * @param filename      the filename to load
    184          */
    185         bool loadFile(const char *fileName);
     181        bool load(Common::SeekableReadStream &stream);
     182        void close();
    186183
    187         /**
    188          * Close an AVI video file
    189          */
    190         void closeFile();
     184        bool isVideoLoaded() const { return _fileStream != 0; }
     185        uint16 getWidth() const { return _header.width; }
     186        uint16 getHeight() const { return _header.height; }
     187        uint32 getFrameCount() const { return _header.totalFrames; }
     188        uint32 getElapsedTime() const;
     189        Surface *decodeNextFrame();
     190        PixelFormat getPixelFormat() const;
     191        byte *getPalette() { _dirtyPalette = false; return _palette; }
     192        bool hasDirtyPalette() const { return _dirtyPalette; }
    191193
    192         bool decodeNextFrame();
    193         int32 getAudioLag();
    194         int32 getFrameRate() { return _vidsHeader.rate / _vidsHeader.scale; }
     194protected:
     195        Common::Rational getFrameRate() const { return Common::Rational(_vidsHeader.rate, _vidsHeader.scale); }
    195196
    196197private:
    197198        Audio::Mixer *_mixer;
     
    202203        AVIStreamHeader _vidsHeader;
    203204        AVIStreamHeader _audsHeader;
    204205        byte _palette[3 * 256];
     206        bool _dirtyPalette;
    205207
     208        Common::SeekableReadStream *_fileStream;
    206209        bool _decodedHeader;
    207210
    208211        Codec *_videoCodec;
     
    223226        static byte char2num(char c);
    224227        static byte getStreamNum(uint32 tag);
    225228        static uint16 getStreamType(uint32 tag);
    226 
    227         Surface *getNextFrame();
    228229};
    229230
    230231} // End of namespace Graphics
  • graphics/video/codecs/codec.h

     
    2828
    2929#include "common/stream.h"
    3030#include "graphics/surface.h"
     31#include "graphics/pixelformat.h"
    3132
    3233namespace Graphics {
    3334
     
    3536public:
    3637        Codec() {}
    3738        virtual ~Codec() {}
     39
    3840        virtual Surface *decodeImage(Common::SeekableReadStream *stream) = 0;
     41        virtual PixelFormat getPixelFormat() const = 0;
    3942};
    4043
    4144} // End of namespace Graphics
  • graphics/video/codecs/msrle.h

     
    3636        ~MSRLEDecoder();
    3737
    3838        Surface *decodeImage(Common::SeekableReadStream *stream);
     39        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
    3940
    4041private:
    4142        byte _bitsPerPixel;
  • graphics/video/codecs/msvideo1.cpp

     
    125125    }
    126126}
    127127
    128 Graphics::Surface *MSVideo1Decoder::decodeImage(Common::SeekableReadStream *stream) {
     128Surface *MSVideo1Decoder::decodeImage(Common::SeekableReadStream *stream) {
    129129        if (_bitsPerPixel == 8)
    130130                decode8(stream);
    131131        else {
  • graphics/video/codecs/msvideo1.h

     
    3636        ~MSVideo1Decoder();
    3737
    3838        Surface *decodeImage(Common::SeekableReadStream *stream);
     39        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
    3940
    4041private:
    4142        byte _bitsPerPixel;
  • graphics/video/smk_decoder.cpp

     
    351351
    352352SmackerDecoder::SmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType)
    353353        : _audioStarted(false), _audioStream(0), _mixer(mixer), _soundType(soundType) {
     354        _surface = 0;
     355        _fileStream = 0;
     356        _dirtyPalette = false;
    354357}
    355358
    356359SmackerDecoder::~SmackerDecoder() {
    357         closeFile();
     360        close();
    358361}
    359362
    360 int SmackerDecoder::getHeight() {
    361         if (!_fileStream)
    362                 return 0;
    363         return (_header.flags ? 2 : 1) * _videoInfo.height;
    364 }
     363uint32 SmackerDecoder::getElapsedTime() const {
     364        if (_audioStream)
     365                return _mixer->getSoundElapsedTime(_audioHandle);
    365366
    366 int32 SmackerDecoder::getAudioLag() {
    367         if (!_fileStream)
    368                 return 0;
    369 
    370         int32 frameDelay = getFrameDelay();
    371         int32 videoTime = (_videoInfo.currentFrame + 1) * frameDelay;
    372         int32 audioTime;
    373 
    374         if (!_audioStream) {
    375                 /* No audio.
    376                    Calculate the lag by how much time has gone by since the first frame
    377                    and how much time *should* have passed.
    378                 */
    379 
    380                 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
    381         } else {
    382                 const Audio::Timestamp ts = _mixer->getElapsedTime(_audioHandle);
    383                 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
    384         }
    385 
    386         return videoTime - audioTime;
     367        return VideoDecoder::getElapsedTime();
    387368}
    388369
    389 bool SmackerDecoder::loadFile(const char *fileName) {
    390         int32 frameRate;
     370bool SmackerDecoder::load(Common::SeekableReadStream &stream) {
     371        close();
    391372
    392         closeFile();
     373        _fileStream = &stream;
    393374
    394         _fileStream = SearchMan.createReadStreamForMember(fileName);
    395         if (!_fileStream)
    396                 return false;
    397 
    398375        // Seek to the first frame
    399         _videoInfo.currentFrame = -1;
    400376        _header.signature = _fileStream->readUint32BE();
    401377
    402378        // No BINK support available
     
    408384
    409385        assert(_header.signature == MKID_BE('SMK2') || _header.signature == MKID_BE('SMK4'));
    410386
    411         _videoInfo.width = _fileStream->readUint32LE();
    412         _videoInfo.height = _fileStream->readUint32LE();
    413         _videoInfo.frameCount = _fileStream->readUint32LE();
    414         frameRate = _fileStream->readSint32LE();
     387        uint32 width = _fileStream->readUint32LE();
     388        uint32 height = _fileStream->readUint32LE();
     389        _frameCount = _fileStream->readUint32LE();
     390        int32 frameRate = _fileStream->readSint32LE();
    415391
    416         if (frameRate > 0) {
    417                 _videoInfo.frameRate = 1000 / frameRate;
    418                 _videoInfo.frameDelay = frameRate * 100;
    419         } else if (frameRate < 0) {
    420                 _videoInfo.frameRate = 100000 / (-frameRate);
    421                 _videoInfo.frameDelay = -frameRate;
    422         } else {
    423                 _videoInfo.frameRate = 10;
    424                 _videoInfo.frameDelay = 10000;
    425         }
     392        if (frameRate > 0)
     393                _frameRate = 1000 / frameRate;
     394        else if (frameRate < 0)
     395                _frameRate = 100000 / (-frameRate);
     396        else
     397                _frameRate = 10;
    426398
    427399        // Flags are determined by which bit is set, which can be one of the following:
    428400        // 0 - set to 1 if file contains a ring frame.
     
    447419        _header.fullSize = _fileStream->readUint32LE();
    448420        _header.typeSize = _fileStream->readUint32LE();
    449421
    450         uint32 audioInfo;
    451422        for (i = 0; i < 7; ++i) {
    452423                // AudioRate - Frequency and format information for each sound track, up to 7 audio tracks.
    453424                // The 32 constituent bits have the following meaning:
     
    458429                // * bits 27-26 - if both set to zero - use v2 sound decompression
    459430                // * bits 25-24 - unused
    460431                // * bits 23-0 - audio sample rate
    461                 audioInfo = _fileStream->readUint32LE();
     432                uint32 audioInfo = _fileStream->readUint32LE();
    462433                _header.audioInfo[i].isCompressed = audioInfo & 0x80000000;
    463434                _header.audioInfo[i].hasAudio = audioInfo & 0x40000000;
    464435                _header.audioInfo[i].is16Bits = audioInfo & 0x20000000;
     
    467438                                                                                                !(audioInfo & 0x4000000);
    468439                _header.audioInfo[i].sampleRate = audioInfo & 0xFFFFFF;
    469440
    470                 if (_header.audioInfo[i].hasAudio && i == 0) {
     441                if (_header.audioInfo[i].hasAudio && i == 0)
    471442                        _audioStream = Audio::makeQueuingAudioStream(_header.audioInfo[0].sampleRate, _header.audioInfo[0].isStereo);
    472                 }
    473443        }
    474444
    475445        _header.dummy = _fileStream->readUint32LE();
    476446
    477         _frameSizes = (uint32 *)malloc(_videoInfo.frameCount * sizeof(uint32));
    478         for (i = 0; i < _videoInfo.frameCount; ++i)
     447        _frameSizes = new uint32[_frameCount];
     448        for (i = 0; i < _frameCount; ++i)
    479449                _frameSizes[i] = _fileStream->readUint32LE();
    480450
    481         _frameTypes = (byte *)malloc(_videoInfo.frameCount);
    482         for (i = 0; i < _videoInfo.frameCount; ++i)
     451        _frameTypes = new byte[_frameCount];
     452        for (i = 0; i < _frameCount; ++i)
    483453                _frameTypes[i] = _fileStream->readByte();
    484454
    485455        byte *huffmanTrees = new byte[_header.treesSize];
     
    494464
    495465        delete[] huffmanTrees;
    496466
    497         _videoFrameBuffer = (byte *)malloc(2 * _videoInfo.width * _videoInfo.height);
    498         memset(_videoFrameBuffer, 0, 2 * _videoInfo.width * _videoInfo.height);
    499         _palette = (byte *)malloc(3 * 256);
    500         memset(_palette, 0, 3 * 256);
     467        _surface = new Graphics::Surface();
    501468
    502         _videoInfo.firstframeOffset = _fileStream->pos();
     469        // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled)
     470        _surface->create(width, height * (_header.flags ? 2 : 1), 1);
    503471
     472        _palette = (byte *)malloc(3 * 256);
     473        memset(_palette, 0, 3 * 256);
    504474        return true;
    505475}
    506476
    507 void SmackerDecoder::closeFile() {
     477void SmackerDecoder::close() {
    508478        if (!_fileStream)
    509479                return;
    510480
     
    517487        delete _fileStream;
    518488        _fileStream = 0;
    519489
     490        _surface->free();
     491        delete _surface;
     492        _surface = 0;
     493
    520494        delete _MMapTree;
    521495        delete _MClrTree;
    522496        delete _FullTree;
    523497        delete _TypeTree;
    524498
    525         free(_frameSizes);
    526         free(_frameTypes);
    527         free(_videoFrameBuffer);
     499        delete[] _frameSizes;
     500        delete[] _frameTypes;
    528501        free(_palette);
     502
     503        reset();
    529504}
    530505
    531 bool SmackerDecoder::decodeNextFrame() {
     506Surface *SmackerDecoder::decodeNextFrame() {
    532507        uint i;
    533508        uint32 chunkSize = 0;
    534509        uint32 dataSizeUnpacked = 0;
    535510
    536511        uint32 startPos = _fileStream->pos();
    537512
    538         _videoInfo.currentFrame++;
     513        _curFrame++;
    539514
    540         if (_videoInfo.currentFrame == 0)
    541                 _videoInfo.startTime = g_system->getMillis();
    542 
    543515        // Check if we got a frame with palette data, and
    544516        // call back the virtual setPalette function to set
    545517        // the current palette
    546         if (_frameTypes[_videoInfo.currentFrame] & 1) {
     518        if (_frameTypes[_curFrame] & 1) {
    547519                unpackPalette();
    548                 setPalette(_palette);
     520                _dirtyPalette = true;
    549521        }
    550522
    551523        // Load audio tracks
    552524        for (i = 0; i < 7; ++i) {
    553                 if (!(_frameTypes[_videoInfo.currentFrame] & (2 << i)))
     525                if (!(_frameTypes[_curFrame] & (2 << i)))
    554526                        continue;
    555527
    556528                chunkSize = _fileStream->readUint32LE();
     
    598570                }
    599571        }
    600572
    601         uint32 frameSize = _frameSizes[_videoInfo.currentFrame] & ~3;
     573        uint32 frameSize = _frameSizes[_curFrame] & ~3;
    602574
    603575        if (_fileStream->pos() - startPos > frameSize)
    604                 exit(1);
     576                error("Smacker actual frame size exceeds recorded frame size");
    605577
    606578        uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos);
    607579
     
    615587        _FullTree->reset();
    616588        _TypeTree->reset();
    617589
    618         uint bw = _videoInfo.width / 4;
    619         uint bh = _videoInfo.height / 4;
    620         uint stride = _videoInfo.width;
    621         uint block = 0, blocks = bw*bh;
    622 
     590        // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled)
    623591        uint doubleY = _header.flags ? 2 : 1;
    624592
     593        uint bw = getWidth() / 4;
     594        uint bh = getHeight() / doubleY / 4;
     595        uint stride = getWidth();
     596        uint block = 0, blocks = bw*bh;
     597
    625598        byte *out;
    626599        uint type, run, j, mode;
    627600        uint32 p1, p2, clr, map;
     
    636609                        while (run-- && block < blocks) {
    637610                                clr = _MClrTree->getCode(bs);
    638611                                map = _MMapTree->getCode(bs);
    639                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     612                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    640613                                hi = clr >> 8;
    641614                                lo = clr & 0xff;
    642615                                for (i = 0; i < 4; i++) {
     
    669642                        }
    670643
    671644                        while (run-- && block < blocks) {
    672                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     645                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    673646                                switch (mode) {
    674647                                        case 0:
    675648                                                for (i = 0; i < 4; ++i) {
     
    735708                        uint32 col;
    736709                        mode = type >> 8;
    737710                        while (run-- && block < blocks) {
    738                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     711                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    739712                                col = mode * 0x01010101;
    740713                                for (i = 0; i < 4 * doubleY; ++i) {
    741714                                        out[0] = out[1] = out[2] = out[3] = col;
     
    751724
    752725        free(_frameData);
    753726
    754         return !endOfVideo();
     727        if (_curFrame == 0)
     728                _startTime = g_system->getMillis();
     729
     730        return _surface;
    755731}
    756732
    757733void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize,
     
    806782                // If the sample is stereo, the data is stored for the left and right channel, respectively
    807783                // (the exact opposite to the base values)
    808784                if (!is16Bits) {
    809 
    810785                        for (int k = 0; k < (isStereo ? 2 : 1); k++) {
    811786                                bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS));
    812787                                *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80;
    813788                                curPos++;
    814789                        }
    815 
    816790                } else {
    817 
    818791                        for (int k = 0; k < (isStereo ? 2 : 1); k++) {
    819792                                bases[k] += (int16) (audioTrees[k * 2]->getCode(audioBS) |
    820793                                                    (audioTrees[k * 2 + 1]->getCode(audioBS) << 8));
     
    887860        }
    888861
    889862        _fileStream->seek(startPos + len);
    890 
    891863        free(chunk);
    892864}
    893865
  • graphics/video/smk_decoder.h

     
    2626#ifndef GRAPHICS_VIDEO_SMK_PLAYER_H
    2727#define GRAPHICS_VIDEO_SMK_PLAYER_H
    2828
    29 #include "graphics/video/video_player.h"
     29#include "graphics/video/video_decoder.h"
    3030#include "sound/mixer.h"
    3131
    3232namespace Audio {
     
    5151 *  - sword1
    5252 *  - sword2
    5353 */
    54 class SmackerDecoder : public VideoDecoder {
     54class SmackerDecoder : public FixedRateVideoDecoder {
    5555public:
    5656        SmackerDecoder(Audio::Mixer *mixer,
    5757                        Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
    5858        virtual ~SmackerDecoder();
    5959
    60         int getHeight();
    61         int32 getAudioLag();
     60        bool load(Common::SeekableReadStream &stream);
     61        void close();
    6262
    63         /**
    64          * Load an SMK encoded video file
    65          * @param filename      the filename to load
    66          */
    67         bool loadFile(const char *filename);
     63        bool isVideoLoaded() const { return _fileStream != 0; }
     64        uint16 getWidth() const { return _surface->w; }
     65        uint16 getHeight() const { return _surface->h; }
     66        uint32 getFrameCount() const { return _frameCount; }
     67        uint32 getElapsedTime() const;
     68        Surface *decodeNextFrame();
     69        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
     70        byte *getPalette() { _dirtyPalette = false; return _palette; }
     71        bool hasDirtyPalette() const { return _dirtyPalette; }
    6872
    69         /**
    70          * Close an SMK encoded video file
    71          */
    72         void closeFile();
     73protected:
     74        Common::Rational getFrameRate() const { return _frameRate; }
     75        Common::SeekableReadStream *_fileStream;
    7376
    74         bool decodeNextFrame();
    75 
    7677private:
    7778        void unpackPalette();
    7879        // Possible runs of blocks
     
    111112        byte *_frameData;
    112113        // The RGB palette
    113114        byte *_palette;
     115        bool _dirtyPalette;
    114116
     117        uint32 _frameRate;
     118        uint32 _frameCount;
     119        Surface *_surface;
     120
    115121        Audio::Mixer::SoundType _soundType;
    116122        Audio::Mixer *_mixer;
    117123        bool _audioStarted;
  • graphics/video/video_decoder.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/graphics/video/video_decoder.cpp $
     22 * $Id$
     23 *
     24 */
     25
     26#include "graphics/video/video_decoder.h"
     27
     28#include "common/file.h"
     29#include "common/system.h"
     30
     31namespace Graphics {
     32
     33VideoDecoder::VideoDecoder() {
     34        reset();
     35}
     36
     37bool VideoDecoder::loadFile(const Common::String &filename) {
     38        Common::File *file = new Common::File();
     39
     40        if (!file->open(filename)) {
     41                delete file;
     42                return false;
     43        }
     44
     45        return load(*file);
     46}
     47
     48uint32 VideoDecoder::getElapsedTime() const {
     49        return g_system->getMillis() - _startTime;
     50}
     51
     52void VideoDecoder::setSystemPalette() {
     53        byte *vidPalette = getPalette();
     54        byte *sysPalette = new byte[256 * 4];
     55
     56        for (uint16 i = 0; i < 256; i++) {
     57                sysPalette[i * 4]     = vidPalette[i * 3];
     58                sysPalette[i * 4 + 1] = vidPalette[i * 3 + 1];
     59                sysPalette[i * 4 + 2] = vidPalette[i * 3 + 2];
     60                sysPalette[i * 4 + 3] = 0;
     61        }
     62
     63        g_system->setPalette(sysPalette, 0, 256);
     64        delete[] sysPalette;
     65}
     66
     67bool VideoDecoder::needsUpdate() const {       
     68        return !endOfVideo() && getTimeToNextFrame() == 0;
     69}
     70
     71void VideoDecoder::reset() {
     72        _curFrame = -1;
     73        _startTime = 0;
     74}
     75
     76bool VideoDecoder::endOfVideo() const {
     77        return !isVideoLoaded() || getCurFrame() >= (int32)getFrameCount() - 1;
     78}
     79
     80uint32 FixedRateVideoDecoder::getTimeToNextFrame() const {
     81        if (endOfVideo() || _curFrame < 0)
     82                return 0;
     83
     84        uint32 elapsedTime = getElapsedTime();
     85        uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1);
     86
     87        // If the time that the next frame should be shown has past
     88        // the frame should be shown ASAP.
     89        if (nextFrameStartTime <= elapsedTime)
     90                return 0;
     91
     92        return nextFrameStartTime - elapsedTime;
     93}
     94
     95uint32 FixedRateVideoDecoder::getFrameBeginTime(uint32 frame) const {
     96        Common::Rational beginTime = frame * 1000;
     97        beginTime /= getFrameRate();
     98        return beginTime.toInt();
     99}
     100
     101} // End of namespace Graphics