Ticket #9141: video_decoder_rewrite.diff

File video_decoder_rewrite.diff, 132.0 KB (added by SF/mthreepwood, 14 years ago)

Patch against r48158

  • engines/mohawk/video/cinepak.h

     
    6565        ~CinepakDecoder();
    6666
    6767        Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
     68        Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
    6869
    6970private:
    7071        CinepakFrame _curFrame;
  • engines/mohawk/video/rpza.h

     
    3737        ~RPZADecoder() { delete _surface; }
    3838
    3939        Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
     40        Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
    4041
    4142private:
    4243        Graphics::Surface *_surface;
  • engines/mohawk/video/smc.h

     
    4343        ~SMCDecoder() { delete _surface; }
    4444
    4545        Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
     46        Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
    4647
    4748private:
    4849        Graphics::Surface *_surface;
  • engines/mohawk/video/qtrle.h

     
    3737        ~QTRLEDecoder();
    3838
    3939        Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
     40        Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
    4041
    4142private:
    4243        byte _bitsPerPixel;
  • engines/mohawk/jpeg.h

     
    4545        ~JPEGDecoder();
    4646
    4747        Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
     48        Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; }
    4849
    4950private:
    5051        Graphics::PixelFormat _pixelFormat;
  • engines/tucker/sequences.cpp

     
    760760}
    761761
    762762bool AnimationSequencePlayer::decodeNextAnimationFrame(int index) {
    763         bool framesLeft = _flicPlayer[index].decodeNextFrame();
     763        ::Graphics::Surface *surface = _flicPlayer[index].decodeNextFrame();
     764
    764765        if (_seqNum == 19) {
    765                 _flicPlayer[index].copyFrameToBuffer(_offscreenBuffer, 0, 0, kScreenWidth);
     766                for (uint16 y = 0; (y < surface->h) && (y < kScreenHeight); y++)
     767                        memcpy(_offscreenBuffer + y * kScreenWidth, (byte *)surface->pixels + y * surface->pitch, surface->w);
    766768        } else {
    767769                _flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth);
    768770                ++_frameCounter;
    769771        }
    770         if (index == 0) {
    771                 if (_flicPlayer[index].paletteChanged()) {
    772                         getRGBPalette(index);
    773                 }
    774         }
    775         return framesLeft;
     772
     773        if (index == 0 && _flicPlayer[index].hasDirtyPalette())
     774                getRGBPalette(index);
     775
     776        return !_flicPlayer[index].endOfVideo();
    776777}
    777778
    778779void AnimationSequencePlayer::loadIntroSeq17_18() {
     
    797798        // The intro credits animation. This uses 2 animations: the foreground one, which
    798799        // is the actual intro credits, and the background one, which is an animation of
    799800        // cogs, and is being replayed when an intro credit appears
    800         if (_flicPlayer[0].getCurFrame() >= 116) {
    801                 if (!_flicPlayer[1].decodeNextFrame()) {
     801        ::Graphics::Surface *surface = 0;
     802
     803        if (_flicPlayer[0].getCurFrame() >= 117) {
     804                surface = _flicPlayer[1].decodeNextFrame();
     805                if (_flicPlayer[1].endOfVideo())
    802806                        _flicPlayer[1].reset();
    803                 }
    804807        }
     808
    805809        bool framesLeft = decodeNextAnimationFrame(0);
    806         for (int i = 0; i < kScreenWidth * kScreenHeight; ++i) {
    807                 if (_offscreenBuffer[i] == 0) {
    808                         _offscreenBuffer[i] = _flicPlayer[1].getPixel(i);
    809                 }
    810         }
    811         if (!framesLeft) {
     810
     811        if (surface)
     812                for (int i = 0; i < kScreenWidth * kScreenHeight; ++i)
     813                        if (_offscreenBuffer[i] == 0)
     814                                _offscreenBuffer[i] = *((byte *)surface->pixels + i);
     815
     816        if (!framesLeft)
    812817                _changeToNextSequence = true;
    813         }
    814818}
    815819
    816820void AnimationSequencePlayer::displayLoadingScreen() {
     
    864868void AnimationSequencePlayer::playIntroSeq3_4() {
    865869        if (!_updateScreenPicture) {
    866870                bool framesLeft = decodeNextAnimationFrame(0);
    867                 if (_flicPlayer[0].getCurFrame() == 706) {
     871                if (_flicPlayer[0].getCurFrame() == 707) {
    868872                        initPicPart4();
    869873                }
    870874                if (!framesLeft) {
     
    903907}
    904908
    905909void AnimationSequencePlayer::drawPic1Part10() {
     910        ::Graphics::Surface *surface = _flicPlayer[0].decodeNextFrame();
     911        _flicPlayer[0].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth);
     912        ++_frameCounter;
     913
     914        if (_flicPlayer[0].hasDirtyPalette())
     915                getRGBPalette(0);
     916
    906917        int offset = 0;
    907918        for (int y = 0; y < kScreenHeight; ++y) {
    908919                for (int x = 0; x < kScreenWidth; ++x) {
    909                         byte color = _flicPlayer[0].getPixel(offset);
    910                         if (color == 0) {
     920                        byte color = *((byte *)surface->pixels + offset);
     921
     922                        if (color == 0)
    911923                                color = _picBufPtr[800 + y * 640 + _updateScreenWidth + x];
    912                         }
     924
    913925                        _offscreenBuffer[offset++] = color;
    914926                }
    915927        }
     
    924936}
    925937
    926938void AnimationSequencePlayer::playIntroSeq9_10() {
    927         bool framesLeft = decodeNextAnimationFrame(0);
    928         if (_flicPlayer[0].getCurFrame() >= 264 && _flicPlayer[0].getCurFrame() <= 295) {
     939        if (_flicPlayer[0].getCurFrame() >= 265 && _flicPlayer[0].getCurFrame() <= 296) {
    929940                drawPic1Part10();
    930941                _updateScreenWidth += 6;
    931         } else if (_flicPlayer[0].getCurFrame() == 984) {
     942        } else if (_flicPlayer[0].getCurFrame() == 985) {
     943                decodeNextAnimationFrame(0);
    932944                drawPic2Part10();
    933         } else if (_flicPlayer[0].getCurFrame() >= 988 && _flicPlayer[0].getCurFrame() <= 996) {
     945        } else if (_flicPlayer[0].getCurFrame() >= 989 && _flicPlayer[0].getCurFrame() <= 997) {
    934946                drawPic1Part10();
    935947                _updateScreenWidth -= 25;
    936948                if (_updateScreenWidth < 0) {
    937949                        _updateScreenWidth = 0;
    938950                }
    939951        }
    940         if (!framesLeft) {
     952
     953        if (_flicPlayer[0].endOfVideo())
    941954                _changeToNextSequence = true;
    942         }
    943955}
    944956
    945957void AnimationSequencePlayer::loadIntroSeq21_22() {
  • engines/saga/scene.h

     
    424424        int DinoStartProc();
    425425        int FTA2StartProc();
    426426        int FTA2EndProc(FTA2Endings whichEnding);
     427        void playMovie(const char *filename);
    427428
    428429        void IHNMLoadCutaways();
    429430        bool checkKey();
  • engines/saga/introproc_saga2.cpp

     
    4040int Scene::DinoStartProc() {
    4141        _vm->_gfx->showCursor(false);
    4242
    43         Graphics::SmackerDecoder *smkDecoder = new Graphics::SmackerDecoder(_vm->_mixer);
    44         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(smkDecoder);
    45         if (smkDecoder->loadFile("testvid.smk"))
    46                 player->playVideo();        // Play introduction
    47         smkDecoder->closeFile();
    48         delete player;
    49         delete smkDecoder;
     43        playMovie("testvid.smk");
    5044
    5145        // HACK: Forcibly quit here
    5246        _vm->quitGame();
     
    5751int Scene::FTA2StartProc() {
    5852        _vm->_gfx->showCursor(false);
    5953
    60         Graphics::SmackerDecoder *smkDecoder = new Graphics::SmackerDecoder(_vm->_mixer);
    61         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(smkDecoder);
    62         if (smkDecoder->loadFile("trimark.smk"))
    63                 player->playVideo();      // Show Ignite logo
    64         smkDecoder->closeFile();
    65         if (smkDecoder->loadFile("intro.smk"))
    66                 player->playVideo();        // Play introduction
    67         smkDecoder->closeFile();
    68         delete player;
    69         delete smkDecoder;
     54        playMovie("trimark.smk");
     55        playMovie("intro.smk");
    7056
    7157        // HACK: Forcibly quit here
    7258        _vm->quitGame();
     
    10086        _vm->_gfx->showCursor(false);
    10187
    10288        // Play ending
    103         Graphics::SmackerDecoder *smkDecoder = new Graphics::SmackerDecoder(_vm->_mixer);
    104         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(smkDecoder);
    105         if (smkDecoder->loadFile(videoName)) {
    106                 player->playVideo();
    107                 smkDecoder->closeFile();
    108         }
    109         delete player;
    110         delete smkDecoder;
     89        playMovie(videoName);
    11190
    11291        return SUCCESS;
    11392}
    11493
     94void Scene::playMovie(const char *filename) {
     95        Graphics::SmackerDecoder *smkDecoder = new Graphics::SmackerDecoder(_vm->_mixer);
     96
     97        if (!smkDecoder->loadFile(filename))
     98                return;
     99
     100        uint16 x = (g_system->getWidth() - smkDecoder->getWidth()) / 2;
     101        uint16 y = (g_system->getHeight() - smkDecoder->getHeight()) / 2;
     102
     103        while (!_vm->shouldQuit() && !smkDecoder->endOfVideo()) {
     104                if (smkDecoder->needsUpdate()) {
     105                        Graphics::Surface *frame = smkDecoder->decodeNextFrame();
     106                        if (frame) {
     107                                _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
     108
     109                                if (smkDecoder->hasDirtyPalette())
     110                                        smkDecoder->setSystemPalette();
     111
     112                                _vm->_system->updateScreen();
     113                        }
     114                }
     115       
     116                Common::Event event;
     117                while (_vm->_system->getEventManager()->pollEvent(event))
     118                        ;
     119
     120                _vm->_system->delayMillis(10);
     121        }
     122}
     123
    115124} // End of namespace Saga
    116125
    117126#endif
  • engines/sci/console.cpp

     
    223223        if (!_videoFile.empty()) {
    224224                _engine->_gfxCursor->kernelHide();
    225225
     226                Graphics::VideoDecoder *videoDecoder = 0;
     227
    226228                if (_videoFile.hasSuffix(".seq")) {
    227                         SeqDecoder *seqDecoder = new SeqDecoder();
    228                         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder);
    229                         if (seqDecoder->loadFile(_videoFile.c_str(), _videoFrameDelay))
    230                                 player->playVideo();
    231                         else
    232                                 DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str());
    233                         seqDecoder->closeFile();
    234                         delete player;
    235                         delete seqDecoder;
    236                 } else if (_videoFile.hasSuffix(".avi")) {
    237                         Graphics::AviDecoder *aviDecoder = new Graphics::AviDecoder(g_system->getMixer());
    238                         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(aviDecoder);
    239                         if (aviDecoder->loadFile(_videoFile.c_str()))
    240                                 player->playVideo();
    241                         else
    242                                 DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str());
    243                         aviDecoder->closeFile();
    244                         delete player;
    245                         delete aviDecoder;
     229                        videoDecoder = new SeqDecoder();
     230                        ((SeqDecoder *)videoDecoder)->setFrameDelay(_videoFrameDelay);
     231#ifdef ENABLE_SCI32
    246232                } else if (_videoFile.hasSuffix(".vmd")) {
    247 #ifdef ENABLE_SCI32
    248                         VMDDecoder *vmdDecoder = new VMDDecoder(g_system->getMixer());
    249                         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(vmdDecoder);
    250                         if (vmdDecoder->loadFile(_videoFile.c_str()))
    251                                 player->playVideo();
    252                         else
    253                                 DebugPrintf("Failed to open movie file %s\n", _videoFile.c_str());
    254                         vmdDecoder->closeFile();
    255                         delete player;
    256                         delete vmdDecoder;
     233                        videoDecoder = new VMDDecoder(g_system->getMixer());
    257234#endif
     235                } else if (_videoFile.hasSuffix(".avi")) {
     236                        videoDecoder = new Graphics::AviDecoder(g_system->getMixer());
    258237                }
    259238
     239                if (videoDecoder && videoDecoder->loadFile(_videoFile)) {
     240                        uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2;
     241                        uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2;
     242
     243                        while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) {                       
     244                                if (videoDecoder->needsUpdate()) {
     245                                        Graphics::Surface *frame = videoDecoder->decodeNextFrame();
     246                                        if (frame) {
     247                                                g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
     248
     249                                                if (videoDecoder->hasDirtyPalette())
     250                                                        videoDecoder->setSystemPalette();
     251
     252                                                g_system->updateScreen();
     253                                        }
     254                                }
     255
     256                                Common::Event event;
     257                                while (g_system->getEventManager()->pollEvent(event))
     258                                        ;
     259
     260                                g_system->delayMillis(10);
     261                        }
     262               
     263                        delete videoDecoder;
     264                } else
     265                        warning("Could not play video %s\n", _videoFile.c_str());
     266
    260267                _engine->_gfxCursor->kernelShow();
    261 
    262268                _videoFile.clear();
    263269                _videoFrameDelay = 0;
    264270        }
  • engines/sci/engine/kgraphics.cpp

     
    10761076}
    10771077
    10781078reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
    1079         bool playedVideo = false;
    1080 
    10811079        // Hide the cursor if it's showing and then show it again if it was
    10821080        // previously visible.
    10831081        bool reshowCursor;
     
    10851083        reshowCursor = g_sci->_gfxCursor->isVisible();
    10861084        if (reshowCursor)
    10871085                g_sci->_gfxCursor->kernelHide();
     1086               
     1087        Graphics::VideoDecoder *videoDecoder = 0;
    10881088
    10891089        if (argv[0].segment != 0) {
    10901090                // DOS SEQ
    10911091                // SEQ's are called with no subops, just the string and delay
    10921092                Common::String filename = s->_segMan->getString(argv[0]);
    1093                 int delay = argv[1].toUint16(); // Time between frames in ticks
    10941093
    10951094                SeqDecoder *seqDecoder = new SeqDecoder();
    1096                 Graphics::VideoPlayer *player = new Graphics::VideoPlayer(seqDecoder);
    1097                 if (seqDecoder->loadFile(filename.c_str(), delay)) {
    1098                         player->playVideo();
    1099                         playedVideo = true;
    1100                 } else {
     1095                seqDecoder->setFrameDelay(argv[1].toUint16());
     1096                videoDecoder = seqDecoder;
     1097               
     1098                if (!videoDecoder->loadFile(filename)) {
    11011099                        warning("Failed to open movie file %s", filename.c_str());
     1100                        delete videoDecoder;
     1101                        videoDecoder = 0;
    11021102                }
    1103                 seqDecoder->closeFile();
    1104                 delete player;
    1105                 delete seqDecoder;
    11061103        } else {
    11071104                // Windows AVI (Macintosh QuickTime? Need to check KQ6 Macintosh)
    11081105                // TODO: This appears to be some sort of subop. case 0 contains the string
     
    11211118                switch (argv[0].toUint16()) {
    11221119                case 0: {
    11231120                        Common::String filename = s->_segMan->getString(argv[1]);
    1124                         Graphics::AviDecoder *aviDecoder = new Graphics::AviDecoder(g_system->getMixer());
    1125                         Graphics::VideoPlayer *player = new Graphics::VideoPlayer(aviDecoder);
    1126                         if (aviDecoder->loadFile(filename.c_str())) {
    1127                                 player->playVideo();
    1128                                 playedVideo = true;
    1129                         } else {
     1121                        videoDecoder = new Graphics::AviDecoder(g_system->getMixer());
     1122
     1123                        if (!videoDecoder->loadFile(filename.c_str())) {
    11301124                                warning("Failed to open movie file %s", filename.c_str());
     1125                                delete videoDecoder;
     1126                                videoDecoder = 0;
    11311127                        }
    1132                         aviDecoder->closeFile();
    1133                         delete player;
    1134                         delete aviDecoder;
    11351128                        break;
    11361129                }
    11371130                default:
     
    11391132                }
    11401133        }
    11411134
    1142         if (playedVideo)
     1135        if (videoDecoder) {
     1136                uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2;
     1137                uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2;
     1138
     1139                while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) {                       
     1140                        if (videoDecoder->needsUpdate()) {
     1141                                Graphics::Surface *frame = videoDecoder->decodeNextFrame();
     1142                                if (frame) {
     1143                                        g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
     1144
     1145                                        if (videoDecoder->hasDirtyPalette())
     1146                                                videoDecoder->setSystemPalette();
     1147
     1148                                        g_system->updateScreen();
     1149                                }
     1150                        }
     1151
     1152                        Common::Event event;
     1153                        while (g_system->getEventManager()->pollEvent(event))
     1154                                ;
     1155
     1156                        g_system->delayMillis(10);
     1157                }
     1158               
     1159                delete videoDecoder;
    11431160                g_sci->_gfxScreen->kernelSyncWithFramebuffer();
     1161        }
    11441162
    11451163        if (reshowCursor)
    11461164                g_sci->_gfxCursor->kernelShow();
  • engines/sci/video/vmd_decoder.h

     
    2929#define GRAPHICS_VIDEO_VMD_DECODER_H
    3030
    3131#include "graphics/video/coktelvideo/coktelvideo.h"
    32 #include "graphics/video/video_player.h"
     32#include "graphics/video/video_decoder.h"
    3333#include "sound/mixer.h"
    3434
    3535namespace Sci {
     
    4949 * - Shivers 2: Harvest of Souls
    5050 * - Torin's Passage
    5151 */
    52 class VMDDecoder : public Graphics::VideoDecoder {
     52class VMDDecoder : public Graphics::FixedRateVideoDecoder {
    5353public:
    5454        VMDDecoder(Audio::Mixer *mixer);
    5555        virtual ~VMDDecoder();
    5656
    5757        uint32 getFrameWaitTime();
    5858
    59         /**
    60          * Load a VMD encoded video file
    61          * @param filename      the filename to load
    62          */
    63         bool loadFile(const char *filename);
     59        bool load(Common::SeekableReadStream &stream);
     60        void close();
    6461
    65         /**
    66          * Close a VMD encoded video file
    67          */
    68         void closeFile();
     62        bool isVideoLoaded() const { return _fileStream != 0; }
     63        uint16 getWidth() const { return _surface->w; }
     64        uint16 getHeight() const { return _surface->h; }
     65        uint32 getFrameCount() const { return _vmdDecoder->getFramesCount(); }
     66        Graphics::Surface *decodeNextFrame();
     67        Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
     68        byte *getPalette() { _dirtyPalette = false; return _palette; }
     69        bool hasDirtyPalette() const { return _dirtyPalette; }
    6970
    70         bool decodeNextFrame();
     71protected:
     72        double getFrameRate() const { return _vmdDecoder->getFrameRate(); }
    7173
    7274private:
    7375        Graphics::Vmd *_vmdDecoder;
    7476        Audio::Mixer *_mixer;
     77        Graphics::Surface *_surface;
     78        Common::SeekableReadStream *_fileStream;
    7579        byte _palette[256 * 3];
     80        bool _dirtyPalette;
    7681
    77         void getPalette();
     82        void loadPaletteFromVMD();
    7883};
    7984
    8085} // End of namespace Graphics
  • engines/sci/video/seq_decoder.h

     
    2626#ifndef SEQ_DECODER_H
    2727#define SEQ_DECODER_H
    2828
    29 #include "graphics/video/video_player.h"
     29#include "graphics/video/video_decoder.h"
    3030
    3131namespace Sci {
    3232
    3333/**
    3434 * Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS
    3535 */
    36 class SeqDecoder : public Graphics::VideoDecoder {
     36class SeqDecoder : public Graphics::FixedRateVideoDecoder {
    3737public:
    38         SeqDecoder() {}
     38        SeqDecoder();
    3939        virtual ~SeqDecoder();
    4040
    41         /**
    42          * Load a SEQ encoded video file
    43          * @param filename      the filename to load
    44          */
    45         bool loadFile(const char *fileName) { return loadFile(fileName, 10); }
     41        bool load(Common::SeekableReadStream &stream);
     42        void close();
     43       
     44        void setFrameDelay(int frameDelay) { _frameDelay = frameDelay; }
    4645
    47         /**
    48          * Load a SEQ encoded video file
    49          * @param filename      the filename to load
    50          * @param frameDelay the delay between frames, in ticks
    51          */
    52         bool loadFile(const char *fileName, int frameDelay);
     46        bool isVideoLoaded() const { return _fileStream != 0; }
     47        uint16 getWidth() const { return 320; }
     48        uint16 getHeight() const { return 200; }
     49        uint32 getFrameCount() const { return _frameCount; }
     50        Graphics::Surface *decodeNextFrame();
     51        Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
     52        byte *getPalette() { _dirtyPalette = false; return _palette; }
     53        bool hasDirtyPalette() const { return _dirtyPalette; }
    5354
    54         /**
    55          * Close a SEQ encoded video file
    56          */
    57         void closeFile();
     55protected:
     56        double getFrameRate() const { assert(_frameDelay); return 60.0 / _frameDelay; }
    5857
    59         bool decodeNextFrame();
    60 
    6158private:
    6259        bool decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey);
     60        uint16 _width, _height;
     61        uint16 _frameDelay;
     62        Common::SeekableReadStream *_fileStream;
     63        byte _palette[256 * 3];
     64        bool _dirtyPalette;
     65        uint32 _frameCount;
     66        Graphics::Surface *_surface;
    6367};
    6468
    6569} // End of namespace Sci
  • engines/sci/video/vmd_decoder.cpp

     
    2727
    2828#include "sci/video/vmd_decoder.h"
    2929
    30 #include "common/archive.h"
    3130#include "common/endian.h"
    3231#include "common/util.h"
    3332#include "common/stream.h"
     
    4241
    4342VMDDecoder::VMDDecoder(Audio::Mixer *mixer) : _mixer(mixer) {
    4443        _vmdDecoder = new Graphics::Vmd(new Graphics::PaletteLUT(5, Graphics::PaletteLUT::kPaletteYUV));
     44        _surface = 0;
     45        _dirtyPalette = false;
     46        _fileStream = 0;
    4547}
    4648
    4749VMDDecoder::~VMDDecoder() {
    48         closeFile();
     50        close();
    4951}
    5052
    51 uint32 VMDDecoder::getFrameWaitTime() {
    52         return _vmdDecoder->getFrameWaitTime();
    53 }
     53bool VMDDecoder::load(Common::SeekableReadStream &stream) {
     54        close();
    5455
    55 bool VMDDecoder::loadFile(const char *fileName) {
    56         closeFile();
    57 
    58         _fileStream = SearchMan.createReadStreamForMember(fileName);
    59         if (!_fileStream)
     56        if (!_vmdDecoder->load(stream))
    6057                return false;
    6158
    62         if (!_vmdDecoder->load(*_fileStream))
    63                 return false;
     59        _fileStream = &stream;
    6460
    65         if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette) {
    66                 getPalette();
    67                 setPalette(_palette);
    68         }
     61        if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette)
     62                loadPaletteFromVMD();
    6963
    7064        if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesSound)
    7165                _vmdDecoder->enableSound(*_mixer);
    7266
    73         _videoInfo.width = _vmdDecoder->getWidth();
    74         _videoInfo.height = _vmdDecoder->getHeight();
    75         _videoInfo.frameCount = _vmdDecoder->getFramesCount();
    76         _videoInfo.frameRate = _vmdDecoder->getFrameRate();
    77         _videoInfo.frameDelay = _videoInfo.frameRate * 100;
    78         _videoInfo.currentFrame = 0;
    79         _videoInfo.firstframeOffset = 0;        // not really necessary for VMDs
    80 
    8167        if (_vmdDecoder->hasExtraData())
    8268                warning("This VMD video has extra embedded data, which is currently not handled");
    8369
    84         _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height];
    85         memset(_videoFrameBuffer, 0, _videoInfo.width * _videoInfo.height);
    86 
    87         _vmdDecoder->setVideoMemory(_videoFrameBuffer, _videoInfo.width, _videoInfo.height);
    88 
     70        _surface = new Graphics::Surface();
     71        _surface->create(_vmdDecoder->getWidth(), _vmdDecoder->getHeight(), 1);
     72        _vmdDecoder->setVideoMemory((byte *)_surface->pixels, _surface->w, _surface->h);
    8973        return true;
    9074}
    9175
    92 void VMDDecoder::closeFile() {
     76void VMDDecoder::close() {
    9377        if (!_fileStream)
    9478                return;
    9579
     
    9882        delete _fileStream;
    9983        _fileStream = 0;
    10084
    101         delete[] _videoFrameBuffer;
    102         _videoFrameBuffer = 0;
     85        _surface->free();
     86        delete _surface;
     87        _surface = 0;
     88
     89        reset();
    10390}
    10491
    105 bool VMDDecoder::decodeNextFrame() {
    106         if (_videoInfo.currentFrame == 0)
    107                 _videoInfo.startTime = g_system->getMillis();
    108 
     92Graphics::Surface *VMDDecoder::decodeNextFrame() {
    10993        Graphics::CoktelVideo::State state = _vmdDecoder->nextFrame();
    11094
    111         if (state.flags & Graphics::CoktelVideo::kStatePalette) {
    112                 getPalette();
    113                 setPalette(_palette);
    114         }
     95        if (state.flags & Graphics::CoktelVideo::kStatePalette)
     96                loadPaletteFromVMD();
    11597
    116         return ++_videoInfo.currentFrame < _videoInfo.frameCount;
     98        if (_curFrame == -1)
     99                _startTime = g_system->getMillis();
     100
     101        _curFrame++;
     102        return _surface;
    117103}
    118104
    119 void VMDDecoder::getPalette() {
     105void VMDDecoder::loadPaletteFromVMD() {
    120106        const byte *pal = _vmdDecoder->getPalette();
    121107
    122108        for (int i = 0; i < 256; i++) {
     
    124110                _palette[i * 3 + 1] = pal[i * 3 + 1] << 2;
    125111                _palette[i * 3 + 2] = pal[i * 3 + 2] << 2;
    126112        }
     113
     114        _dirtyPalette = true;
    127115}
    128116
    129117} // End of namespace Graphics
  • engines/sci/video/seq_decoder.cpp

     
    3535
    3636namespace Sci {
    3737
    38 // SEQ videos always run at 320x200
    39 #define SCREEN_WIDTH 320
    40 #define SCREEN_HEIGHT 200
    41 
    4238enum seqPalTypes {
    4339        kSeqPalVariable = 0,
    4440        kSeqPalConstant = 1
     
    4945        kSeqFrameDiff = 1
    5046};
    5147
     48SeqDecoder::SeqDecoder() {
     49        _fileStream = 0;
     50        _surface = 0;
     51        _dirtyPalette = false;
     52}
     53
    5254SeqDecoder::~SeqDecoder() {
    53         closeFile();
     55        close();
    5456}
    5557
    56 bool SeqDecoder::loadFile(const char *fileName, int frameDelay) {
    57         closeFile();
     58bool SeqDecoder::load(Common::SeekableReadStream &stream) {
     59        close();
    5860
    59         _fileStream = SearchMan.createReadStreamForMember(fileName);
    60         if (!_fileStream)
    61                 return false;
     61        _fileStream = &stream;
     62        _surface = new Graphics::Surface();
     63        _surface->create(getWidth(), getHeight(), 1);
    6264
    63         // Seek to the first frame
    64         _videoInfo.currentFrame = 0;
     65        _frameCount = _fileStream->readUint16LE();
    6566
    66         _videoInfo.width = SCREEN_WIDTH;
    67         _videoInfo.height = SCREEN_HEIGHT;
    68         _videoInfo.frameCount = _fileStream->readUint16LE();
    69         // Our frameDelay is calculated in 1/100 ms, so we convert it here
    70         _videoInfo.frameDelay = 100 * frameDelay * 1000 / 60;
    71         _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height];
    72 
    7367        // Set palette
    7468        int paletteSize = _fileStream->readUint32LE();
    7569
     
    8175        uint16 palColorStart = READ_LE_UINT16(paletteData + 25);
    8276        uint16 palColorCount = READ_LE_UINT16(paletteData + 29);
    8377
    84         byte palette[256 * 4];
    8578        int palOffset = 37;
    8679
    8780        for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) {
    8881                if (palFormat == kSeqPalVariable)
    8982                        palOffset++;
    90                 palette[colorNo * 4 + 0] = paletteData[palOffset++];
    91                 palette[colorNo * 4 + 1] = paletteData[palOffset++];
    92                 palette[colorNo * 4 + 2] = paletteData[palOffset++];
    93                 palette[colorNo * 4 + 3] = 0;
     83                _palette[colorNo * 3 + 0] = paletteData[palOffset++];
     84                _palette[colorNo * 3 + 1] = paletteData[palOffset++];
     85                _palette[colorNo * 3 + 2] = paletteData[palOffset++];
    9486        }
    9587
    96         g_system->setPalette(palette, 0, 256);
    97 
     88        _dirtyPalette = true;
    9889        delete[] paletteData;
    99 
    100         _videoInfo.firstframeOffset = _fileStream->pos();
    101 
    10290        return true;
    10391}
    10492
    105 void SeqDecoder::closeFile() {
     93void SeqDecoder::close() {
    10694        if (!_fileStream)
    10795                return;
    10896
     97        _frameDelay = 0;
     98
    10999        delete _fileStream;
    110100        _fileStream = 0;
    111101
    112         delete[] _videoFrameBuffer;
    113         _videoFrameBuffer = 0;
     102        _surface->free();
     103        delete _surface;
     104        _surface = 0;
     105
     106        reset();
    114107}
    115108
    116 bool SeqDecoder::decodeNextFrame() {
     109Graphics::Surface *SeqDecoder::decodeNextFrame() {
    117110        int16 frameWidth = _fileStream->readUint16LE();
    118111        int16 frameHeight = _fileStream->readUint16LE();
    119112        int16 frameLeft = _fileStream->readUint16LE();
     
    129122
    130123        _fileStream->seek(offset);
    131124
    132         if (_videoInfo.currentFrame == 0)
    133                 _videoInfo.startTime = g_system->getMillis();
    134 
    135125        if (frameType == kSeqFrameFull) {
    136                 byte *dst = _videoFrameBuffer + frameTop * SCREEN_WIDTH + frameLeft;
     126                byte *dst = (byte *)_surface->pixels + frameTop * getWidth() + frameLeft;
    137127
    138128                byte *linebuf = new byte[frameWidth];
    139129
    140130                do {
    141131                        _fileStream->read(linebuf, frameWidth);
    142132                        memcpy(dst, linebuf, frameWidth);
    143                         dst += SCREEN_WIDTH;
     133                        dst += getWidth();
    144134                } while (--frameHeight);
    145135
    146136                delete[] linebuf;
    147137        } else {
    148138                byte *buf = new byte[frameSize];
    149139                _fileStream->read(buf, frameSize);
    150                 decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, _videoFrameBuffer + SCREEN_WIDTH * frameTop, frameLeft, frameWidth, frameHeight, colorKey);
     140                decodeFrame(buf, rleSize, buf + rleSize, frameSize - rleSize, (byte *)_surface->pixels + getWidth() * frameTop, frameLeft, frameWidth, frameHeight, colorKey);
    151141                delete[] buf;
    152142        }
    153143
    154         return ++_videoInfo.currentFrame < _videoInfo.frameCount;
     144        if (_curFrame == -1)
     145                _startTime = g_system->getMillis();
     146
     147        _curFrame++;
     148        return _surface;
    155149}
    156150
    157151#define WRITE_TO_BUFFER(n) \
    158         if (writeRow * SCREEN_WIDTH + writeCol + (n) > SCREEN_WIDTH * height) { \
     152        if (writeRow * getWidth() + writeCol + (n) > getWidth() * height) { \
    159153                warning("SEQ player: writing out of bounds, aborting"); \
    160154                return false; \
    161155        } \
    162156        if (litPos + (n) > litSize) { \
    163157                warning("SEQ player: reading out of bounds, aborting"); \
    164158        } \
    165         memcpy(dest + writeRow * SCREEN_WIDTH + writeCol, litData + litPos, n);
     159        memcpy(dest + writeRow * getWidth() + writeCol, litData + litPos, n);
    166160
    167161bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) {
    168162        int writeRow = 0;
  • engines/sword1/animation.h

     
    2828
    2929#include "graphics/video/dxa_decoder.h"
    3030#include "graphics/video/smk_decoder.h"
    31 #include "graphics/video/video_player.h"
     31#include "graphics/video/video_decoder.h"
    3232
    3333#include "sword1/screen.h"
    3434#include "sword1/sound.h"
     
    6161        DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
    6262        ~DXADecoderWithSound() {}
    6363
    64         int32 getAudioLag();
     64        uint32 getElapsedTime() const;
     65
    6566private:
    6667        Audio::Mixer *_mixer;
    6768        Audio::SoundHandle *_bgSoundHandle;
    6869};
    6970
    70 class MoviePlayer : public Graphics::VideoPlayer {
     71class MoviePlayer {
    7172public:
    7273        MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType);
    7374        virtual ~MoviePlayer();
    7475        bool load(uint32 id);
    7576        void play();
     77
    7678protected:
    7779        SwordEngine *_vm;
    7880        Text *_textMan;
     
    8284        int _textX, _textY, _textWidth, _textHeight;
    8385        DecoderType _decoderType;
    8486
     87        Graphics::VideoDecoder *_decoder;
    8588        Audio::SoundHandle *_bgSoundHandle;
    8689        Audio::AudioStream *_bgSoundStream;
    8790
     91        bool playVideo();
    8892        void performPostProcessing(byte *screen);
     93
     94        byte findBlackPalIndex();
     95        byte findWhitePalIndex();
    8996};
    9097
    9198MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system);
  • engines/sword1/animation.cpp

     
    6868///////////////////////////////////////////////////////////////////////////////
    6969
    7070MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType)
    71         : _vm(vm), _textMan(textMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system), VideoPlayer(decoder) {
     71        : _vm(vm), _textMan(textMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
    7272        _bgSoundStream = NULL;
    7373        _decoderType = decoderType;
     74        _decoder = decoder;
    7475}
    7576
    7677MoviePlayer::~MoviePlayer() {
     
    8687        Common::File f;
    8788        char filename[20];
    8889
    89         if (_decoderType == kVideoDecoderDXA) {
     90        if (_decoderType == kVideoDecoderDXA)
    9091                _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(sequenceList[id]);
    91         } else {
     92        else
    9293                _bgSoundStream = NULL;
    93         }
    9494
    9595        if (SwordEngine::_systemVars.showText) {
    9696                sprintf(filename, "%s.txt", sequenceList[id]);
     
    146146}
    147147
    148148void MoviePlayer::play() {
    149         if (_bgSoundStream) {
     149        if (_bgSoundStream)
    150150                _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
    151         }
     151
    152152        bool terminated = false;
    153153
    154154        _textX = 0;
     
    205205                        for (x = 0; x < _textWidth; x++) {
    206206                                switch (src[x]) {
    207207                                case BORDER_COL:
    208                                         dst[x] = _decoder->getBlack();
     208                                        dst[x] = findBlackPalIndex();
    209209                                        break;
    210210                                case LETTER_COL:
    211                                         dst[x] = _decoder->getWhite();
     211                                        dst[x] = findWhitePalIndex();
    212212                                        break;
    213213                                }
    214214                        }
     
    228228
    229229                for (y = 0; y < _textHeight; y++) {
    230230                        if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
    231                                 memset(dst + _textX, _decoder->getBlack(), _textWidth);
     231                                memset(dst + _textX, findBlackPalIndex(), _textWidth);
    232232                        } else {
    233233                                if (frameX > _textX)
    234                                         memset(dst + _textX, _decoder->getBlack(), frameX - _textX);
     234                                        memset(dst + _textX, findBlackPalIndex(), frameX - _textX);
    235235                                if (frameX + frameWidth < _textX + _textWidth)
    236                                         memset(dst + frameX + frameWidth, _decoder->getBlack(), _textX + _textWidth - (frameX + frameWidth));
     236                                        memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + _textWidth - (frameX + frameWidth));
    237237                        }
    238238
    239239                        dst += _system->getWidth();
     
    244244        }
    245245}
    246246
    247 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
    248         : _mixer(mixer), _bgSoundHandle(bgSoundHandle)  {
     247bool MoviePlayer::playVideo() {
     248        uint16 x = (g_system->getWidth() - _decoder->getWidth()) / 2;
     249        uint16 y = (g_system->getHeight() - _decoder->getHeight()) / 2;
     250
     251        while (!_vm->shouldQuit() && !_decoder->endOfVideo()) {
     252                if (_decoder->needsUpdate()) {
     253                        Graphics::Surface *frame = _decoder->decodeNextFrame();
     254                        if (frame)
     255                                _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
     256
     257                        if (_decoder->hasDirtyPalette())
     258                                _decoder->setSystemPalette();
     259
     260                        Graphics::Surface *screen = _vm->_system->lockScreen();
     261                        performPostProcessing((byte *)screen->pixels);
     262                        _vm->_system->unlockScreen();
     263                        _vm->_system->updateScreen();
     264                }
     265
     266                Common::Event event;
     267                while (_vm->_system->getEventManager()->pollEvent(event))
     268                        if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
     269                                return false;
     270        }
     271
     272        return true;
    249273}
    250274
    251 int32 DXADecoderWithSound::getAudioLag() {
    252         if (!_fileStream)
    253                 return 0;
     275byte MoviePlayer::findBlackPalIndex() {
     276        return 0;
     277}
    254278
    255         if (!_mixer->isSoundHandleActive(*_bgSoundHandle))
    256                 return 0;
     279byte MoviePlayer::findWhitePalIndex() {
     280        return 0xff;
     281}
    257282
    258         int32 frameDelay = getFrameDelay();
    259         int32 videoTime = _videoInfo.currentFrame * frameDelay;
    260         int32 audioTime;
     283DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
     284        : _mixer(mixer), _bgSoundHandle(bgSoundHandle)  {
     285}
    261286
    262         const Audio::Timestamp ts = _mixer->getElapsedTime(*_bgSoundHandle);
    263         audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
     287uint32 DXADecoderWithSound::getElapsedTime() const {
     288        if (_mixer->isSoundHandleActive(*_bgSoundHandle))
     289                return _mixer->getSoundElapsedTime(*_bgSoundHandle);
    264290
    265         return videoTime - audioTime;
     291        return VideoDecoder::getElapsedTime();
    266292}
    267293
    268294///////////////////////////////////////////////////////////////////////////////
  • engines/sword2/animation.h

     
    3030
    3131#include "graphics/video/dxa_decoder.h"
    3232#include "graphics/video/smk_decoder.h"
    33 #include "graphics/video/video_player.h"
     33#include "graphics/video/video_decoder.h"
    3434#include "sound/mixer.h"
    3535
    3636#include "sword2/screen.h"
     
    6363        DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle);
    6464        ~DXADecoderWithSound() {}
    6565
    66         int32 getAudioLag();
     66        uint32 getElapsedTime() const;
    6767private:
    6868        Audio::Mixer *_mixer;
    6969        Audio::SoundHandle *_bgSoundHandle;
    7070};
    7171
    72 class MoviePlayer : public Graphics::VideoPlayer {
     72class MoviePlayer {
    7373public:
    7474        MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType);
    7575        virtual ~MoviePlayer();
     
    8989        int _textX, _textY;
    9090        DecoderType _decoderType;
    9191
     92        Graphics::VideoDecoder *_decoder;
    9293        Audio::SoundHandle *_bgSoundHandle;
    9394        Audio::AudioStream *_bgSoundStream;
    9495
     
    9697        int _leadOutFrame;
    9798
    9899        void performPostProcessing(byte *screen);
     100        bool playVideo();
    99101
    100102        void openTextObject(uint32 index);
    101103        void closeTextObject(uint32 index, byte *screen);
    102104        void drawTextObject(uint32 index, byte *screen);
     105
     106        byte findBlackPalIndex();
     107        byte findWhitePalIndex();
    103108};
    104109
    105110MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system);
  • engines/sword2/animation.cpp

     
    4747///////////////////////////////////////////////////////////////////////////////
    4848
    4949MoviePlayer::MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType)
    50         : _vm(vm), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system), VideoPlayer(decoder) {
     50        : _vm(vm), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) {
    5151        _bgSoundStream = NULL;
    5252        _decoderType = decoderType;
     53        _decoder = decoder;
    5354}
    5455
    5556MoviePlayer:: ~MoviePlayer() {
     
    6263 * @param id the id of the file
    6364 */
    6465bool MoviePlayer::load(const char *name) {
    65         if (_decoderType == kVideoDecoderDXA) {
     66        if (_decoderType == kVideoDecoderDXA)
    6667                _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(name);
    67         } else {
     68        else
    6869                _bgSoundStream = NULL;
    69         }
    7070
    7171        _textSurface = NULL;
    7272
     
    9797        _currentMovieText = 0;
    9898        _leadOut = leadOut;
    9999
    100         if (leadIn) {
     100        if (leadIn)
    101101                _vm->_sound->playMovieSound(leadIn, kLeadInSound);
    102         }
    103102
    104         if (_bgSoundStream) {
     103        if (_bgSoundStream)
    105104                _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream);
    106         }
    107105
    108106        bool terminated = false;
    109107
     
    186184
    187185                                for (int y = 0; y < text->_textSprite.h; y++) {
    188186                                        if (_textY + y < frameY || _textY + y >= frameY + frameHeight) {
    189                                                 memset(dst + _textX, _decoder->getBlack(), text->_textSprite.w);
     187                                                memset(dst + _textX, findBlackPalIndex(), text->_textSprite.w);
    190188                                        } else {
    191189                                                if (frameX > _textX)
    192                                                         memset(dst + _textX, _decoder->getBlack(), frameX - _textX);
     190                                                        memset(dst + _textX, findBlackPalIndex(), frameX - _textX);
    193191                                                if (frameX + frameWidth < _textX + text->_textSprite.w)
    194                                                         memset(dst + frameX + frameWidth, _decoder->getBlack(), _textX + text->_textSprite.w - (frameX + frameWidth));
     192                                                        memset(dst + frameX + frameWidth, findBlackPalIndex(), _textX + text->_textSprite.w - (frameX + frameWidth));
    195193                                        }
    196194
    197195                                        dst += _system->getWidth();
     
    207205void MoviePlayer::drawTextObject(uint32 index, byte *screen) {
    208206        MovieText *text = &_movieTexts[index];
    209207
    210         byte white = _decoder->getWhite();
    211         byte black = _decoder->getBlack();
     208        byte white = findWhitePalIndex();
     209        byte black = findBlackPalIndex();
    212210
    213211        if (text->_textMem && _textSurface) {
    214212                byte *src = text->_textSprite.data;
     
    272270        }
    273271}
    274272
    275 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
    276         : _mixer(mixer), _bgSoundHandle(bgSoundHandle)  {
     273bool MoviePlayer::playVideo() {
     274        uint16 x = (g_system->getWidth() - _decoder->getWidth()) / 2;
     275        uint16 y = (g_system->getHeight() - _decoder->getHeight()) / 2;
     276
     277        while (!_vm->shouldQuit() && !_decoder->endOfVideo()) {
     278                if (_decoder->needsUpdate()) {
     279                        Graphics::Surface *frame = _decoder->decodeNextFrame();
     280                        if (frame)
     281                                _vm->_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
     282
     283                        if (_decoder->hasDirtyPalette())
     284                                _decoder->setSystemPalette();
     285
     286                        Graphics::Surface *screen = _vm->_system->lockScreen();
     287                        performPostProcessing((byte *)screen->pixels);
     288                        _vm->_system->unlockScreen();
     289                        _vm->_system->updateScreen();
     290                }
     291
     292                Common::Event event;
     293                while (_vm->_system->getEventManager()->pollEvent(event))
     294                        if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
     295                                return false;
     296        }
     297
     298        return true;
    277299}
    278300
    279 int32 DXADecoderWithSound::getAudioLag() {
    280         if (!_fileStream)
    281                 return 0;
     301byte MoviePlayer::findBlackPalIndex() {
     302        return 0;
     303}
    282304
    283         if (!_mixer->isSoundHandleActive(*_bgSoundHandle))
    284                 return 0;
     305byte MoviePlayer::findWhitePalIndex() {
     306        return 0xff;
     307}
    285308
    286         int32 frameDelay = getFrameDelay();
    287         int32 videoTime = _videoInfo.currentFrame * frameDelay;
    288         int32 audioTime;
     309DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle)
     310        : _mixer(mixer), _bgSoundHandle(bgSoundHandle)  {
     311}
    289312
    290         const Audio::Timestamp ts = _mixer->getElapsedTime(*_bgSoundHandle);
    291         audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
     313uint32 DXADecoderWithSound::getElapsedTime() const {
     314        if (_mixer->isSoundHandleActive(*_bgSoundHandle))
     315                return _mixer->getSoundElapsedTime(*_bgSoundHandle);
    292316
    293         return videoTime - audioTime;
     317        return VideoDecoder::getElapsedTime();
    294318}
    295319
    296320///////////////////////////////////////////////////////////////////////////////
  • engines/scumm/he/animation_he.h

     
    5656
    5757        void copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint pitch);
    5858        void handleNextFrame();
    59 
    60 protected:
    61         virtual void setPalette(byte *pal);
    6259};
    6360
    6461} // End of namespace Scumm
  • engines/scumm/he/script_v90he.cpp

     
    14371437                        }
    14381438                } else if (_videoParams.status == 165) {
    14391439                        // Stop video
    1440                         _moviePlay->closeFile();
     1440                        _moviePlay->close();
    14411441                }
    14421442                break;
    14431443        default:
     
    14641464                break;
    14651465        case 52:        // Get current frame
    14661466                pop();
    1467                 push(_moviePlay->getCurFrame());
     1467                push(_moviePlay->endOfVideo() ? -1 : (_moviePlay->getCurFrame() + 1));
    14681468                break;
    14691469        case 63:        // Get image number
    14701470                pop();
  • engines/scumm/he/script_v100he.cpp

     
    22542254                        }
    22552255                } else if (_videoParams.status == 19) {
    22562256                        // Stop video
    2257                         _moviePlay->closeFile();
     2257                        _moviePlay->close();
    22582258                }
    22592259                break;
    22602260        default:
     
    29372937                break;
    29382938        case 73:
    29392939                pop();
    2940                 push(_moviePlay->getCurFrame());
     2940                push(_moviePlay->endOfVideo() ? -1 : (_moviePlay->getCurFrame() + 1));
    29412941                break;
    29422942        case 84:
    29432943                pop();
  • engines/scumm/he/animation_he.cpp

     
    4646}
    4747
    4848int MoviePlayer::load(const char *filename, int flags, int image) {
    49         if (isVideoLoaded()) {
    50                 closeFile();
    51         }
     49        if (isVideoLoaded())
     50                close();
    5251
    53         if (!loadFile(filename)) {
     52        if (!loadFile(Common::String(filename))) {
    5453                warning("Failed to load video file %s", filename);
    5554                return -1;
    5655        }
     56
    5757        debug(1, "Playing video %s", filename);
    5858
    59         if (flags & 2) {
     59        if (flags & 2)
    6060                _vm->_wiz->createWizEmptyImage(image, 0, 0, getWidth(), getHeight());
    61         }
    6261
    6362        _flags = flags;
    6463        _wizResNum = image;
    65 
    6664        return 0;
    6765}
    6866
     
    7068        uint h = getHeight();
    7169        uint w = getWidth();
    7270
    73         byte *src = _videoFrameBuffer;
     71        Graphics::Surface *surface = decodeNextFrame();
     72        byte *src = (byte *)surface->pixels;
    7473
     74        if (hasDirtyPalette())
     75                _vm->setPaletteFromPtr(getPalette(), 256);
     76
    7577        if (_vm->_game.features & GF_16BIT_COLOR) {
    7678                dst += y * pitch + x * 2;
    7779                do {
     
    102104}
    103105
    104106void MoviePlayer::handleNextFrame() {
    105         if (!isVideoLoaded()) {
     107        if (!isVideoLoaded())
    106108                return;
    107         }
    108109
    109110        VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
    110111
    111         decodeNextFrame();
    112 
    113112        if (_flags & 2) {
    114113                uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum);
    115114                assert(dstPtr);
     
    128127                _vm->markRectAsDirty(kMainVirtScreen, imageRect);
    129128        }
    130129
    131         if (getCurFrame() == getFrameCount()) {
    132                 closeFile();
    133         }
     130        if (endOfVideo())
     131                close();
    134132}
    135133
    136 void MoviePlayer::setPalette(byte *pal) {
    137         _vm->setPaletteFromPtr(pal, 256);
    138 }
    139 
    140134} // End of namespace Scumm
    141135
    142136#endif // ENABLE_HE
  • engines/agos/animation.h

     
    7272        virtual void handleNextFrame();
    7373        virtual bool processFrame() = 0;
    7474        virtual void startSound() {};
     75
     76protected:
     77        uint32 _firstFrameOffset;
    7578};
    7679
    7780class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXADecoder {
     
    8487        void playVideo();
    8588        void nextFrame();
    8689        virtual void stopVideo();
    87 protected:
    88         void setPalette(byte *pal);
    8990
    9091private:
    9192        void handleNextFrame();
    9293        bool processFrame();
    9394        void startSound();
     95        void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
    9496};
    9597
    9698class MoviePlayerSMK : public MoviePlayer, ::Graphics::SmackerDecoder {
     
    101103        void playVideo();
    102104        void nextFrame();
    103105        virtual void stopVideo();
    104 protected:
    105         void setPalette(byte *pal);
     106
    106107private:
    107108        void handleNextFrame();
    108109        bool processFrame();
    109110        void startSound();
     111        void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
    110112};
    111113
    112114MoviePlayer *makeMoviePlayer(AGOSEngine_Feeble *vm, const char *name);
  • engines/agos/animation.cpp

     
    241241}
    242242
    243243bool MoviePlayerDXA::load() {
    244         char videoName[20];
    245         uint i;
    246 
    247244        if ((_vm->getPlatform() == Common::kPlatformAmiga || _vm->getPlatform() == Common::kPlatformMacintosh) &&
    248245                _vm->_language != Common::EN_ANY) {
    249246                _sequenceNum = 0;
    250                 for (i = 0; i < 90; i++) {
     247                for (uint i = 0; i < 90; i++) {
    251248                        if (!scumm_stricmp(baseName, _sequenceList[i]))
    252249                                _sequenceNum = i;
    253250                }
    254251        }
    255252
    256         sprintf(videoName, "%s.dxa", baseName);
     253        Common::String videoName = Common::String::printf("%s.dxa", baseName);
    257254        if (!loadFile(videoName))
    258                 error("Failed to load video file %s", videoName);
     255                error("Failed to load video file %s", videoName.c_str());
    259256
    260         debug(0, "Playing video %s", videoName);
     257        debug(0, "Playing video %s", videoName.c_str());
    261258
    262259        CursorMan.showMouse(false);
    263260
     261        _firstFrameOffset = _fileStream->pos();
     262
    264263        return true;
    265264}
    266265
     266void MoviePlayerDXA::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
     267        uint h = getHeight();
     268        uint w = getWidth();
     269
     270        Graphics::Surface *surface = decodeNextFrame();
     271        byte *src = (byte *)surface->pixels;
     272        dst += y * pitch + x;
     273
     274        do {
     275                memcpy(dst, src, w);
     276                dst += pitch;
     277                src += w;
     278        } while (--h);
     279
     280        if (hasDirtyPalette())
     281                setSystemPalette();
     282}
     283
    267284void MoviePlayerDXA::playVideo() {
    268285        // Most of the videos included in the Amiga version, reduced the
    269286        // resoluton to 384 x 280, so require the screen to be cleared,
     
    272289                _vm->clearSurfaces();
    273290        }
    274291
    275         while (getCurFrame() < getFrameCount() && !_skipMovie && !_vm->shouldQuit())
     292        while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit())
    276293                handleNextFrame();
    277294}
    278295
    279296void MoviePlayerDXA::stopVideo() {
    280         closeFile();
     297        close();
    281298        _mixer->stopHandle(_bgSound);
    282299}
    283300
     
    318335}
    319336
    320337void MoviePlayerDXA::nextFrame() {
    321         if (_bgSoundStream && _vm->_mixer->isSoundHandleActive(_bgSound) && (_vm->_mixer->getSoundElapsedTime(_bgSound) * getFrameRate()) / 1000 < (uint32)getCurFrame()) {
     338        if (_bgSoundStream && _vm->_mixer->isSoundHandleActive(_bgSound) && needsUpdate()) {
    322339                copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
    323340                return;
    324341        }
    325342
    326         if (_vm->_interactiveVideo == TYPE_LOOPING && getCurFrame() == getFrameCount()) {
    327                 _fileStream->seek(_videoInfo.firstframeOffset);
    328                 _videoInfo.currentFrame = 0;
     343        if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
     344                _fileStream->seek(_firstFrameOffset);
     345                _curFrame = -1;
    329346                startSound();
    330347        }
    331348
    332         if (getCurFrame() < getFrameCount()) {
    333                 decodeNextFrame();
    334                 if (_vm->_interactiveVideo == TYPE_OMNITV) {
     349        if (!endOfVideo()) {
     350                if (_vm->_interactiveVideo == TYPE_OMNITV)
    335351                        copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
    336                 } else if (_vm->_interactiveVideo == TYPE_LOOPING) {
     352                else if (_vm->_interactiveVideo == TYPE_LOOPING)
    337353                        copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
    338                 }
    339354        } else if (_vm->_interactiveVideo == TYPE_OMNITV) {
    340                 closeFile();
     355                close();
    341356                _vm->_interactiveVideo = 0;
    342357                _vm->_variableArray[254] = 6747;
    343358        }
    344359}
    345360
    346361void MoviePlayerDXA::handleNextFrame() {
    347         decodeNextFrame();
    348362        if (processFrame())
    349363                _vm->_system->updateScreen();
    350364
    351365        MoviePlayer::handleNextFrame();
    352366}
    353367
    354 void MoviePlayerDXA::setPalette(byte *pal) {
    355         byte palette[1024];
    356         byte *p = palette;
    357 
    358         for (int i = 0; i < 256; i++) {
    359                 *p++ = *pal++;
    360                 *p++ = *pal++;
    361                 *p++ = *pal++;
    362                 *p++ = 0;
    363         }
    364 
    365         _vm->_system->setPalette(palette, 0, 256);
    366 }
    367 
    368368bool MoviePlayerDXA::processFrame() {
    369369        Graphics::Surface *screen = _vm->_system->lockScreen();
    370370        copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
     
    381381                        // sync case for the subsequent frames.
    382382                        _ticks = _vm->_system->getMillis();
    383383                } else {
    384                         _ticks += getFrameWaitTime();
     384                        _ticks += getTimeToNextFrame();
    385385                        while (_vm->_system->getMillis() < _ticks)
    386386                                _vm->_system->delayMillis(10);
    387387                }
     
    407407}
    408408
    409409bool MoviePlayerSMK::load() {
    410         char videoName[20];
     410        Common::String videoName = Common::String::printf("%s.smk", baseName);
    411411
    412         sprintf(videoName, "%s.smk", baseName);
    413412        if (!loadFile(videoName))
    414                 error("Failed to load video file %s", videoName);
     413                error("Failed to load video file %s", videoName.c_str());
    415414
    416         debug(0, "Playing video %s", videoName);
     415        debug(0, "Playing video %s", videoName.c_str());
    417416
    418417        CursorMan.showMouse(false);
    419418
     419        _firstFrameOffset = _fileStream->pos();
     420
    420421        return true;
    421422}
    422423
     424void MoviePlayerSMK::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
     425        uint h = getHeight();
     426        uint w = getWidth();
     427
     428        Graphics::Surface *surface = decodeNextFrame();
     429        byte *src = (byte *)surface->pixels;
     430        dst += y * pitch + x;
     431
     432        do {
     433                memcpy(dst, src, w);
     434                dst += pitch;
     435                src += w;
     436        } while (--h);
     437
     438        if (hasDirtyPalette())
     439                setSystemPalette();
     440}
     441
    423442void MoviePlayerSMK::playVideo() {
    424         while (getCurFrame() < getFrameCount() && !_skipMovie && !_vm->shouldQuit())
     443        while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit())
    425444                handleNextFrame();
    426445}
    427446
    428447void MoviePlayerSMK::stopVideo() {
    429         closeFile();
     448        close();
    430449}
    431450
    432451void MoviePlayerSMK::startSound() {
    433452}
    434453
    435454void MoviePlayerSMK::handleNextFrame() {
    436         decodeNextFrame();
    437455        processFrame();
    438456
    439457        MoviePlayer::handleNextFrame();
    440458}
    441459
    442460void MoviePlayerSMK::nextFrame() {
    443         if (_vm->_interactiveVideo == TYPE_LOOPING && getCurFrame() == getFrameCount()) {
    444                 _fileStream->seek(_videoInfo.firstframeOffset);
    445                 _videoInfo.currentFrame = 0;
     461        if (_vm->_interactiveVideo == TYPE_LOOPING && endOfVideo()) {
     462                _fileStream->seek(_firstFrameOffset);
     463                _curFrame = -1;
    446464        }
    447465
    448         if (getCurFrame() < getFrameCount()) {
    449                 decodeNextFrame();
     466        if (!endOfVideo()) {
    450467                if (_vm->_interactiveVideo == TYPE_OMNITV) {
    451468                        copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth);
    452469                } else if (_vm->_interactiveVideo == TYPE_LOOPING) {
    453470                        copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
    454471                }
    455472        } else if (_vm->_interactiveVideo == TYPE_OMNITV) {
    456                 closeFile();
     473                close();
    457474                _vm->_interactiveVideo = 0;
    458475                _vm->_variableArray[254] = 6747;
    459476        }
    460477}
    461478
    462 void MoviePlayerSMK::setPalette(byte *pal) {
    463         byte palette[1024];
    464         byte *p = palette;
    465 
    466         for (int i = 0; i < 256; i++) {
    467                 *p++ = *pal++;
    468                 *p++ = *pal++;
    469                 *p++ = *pal++;
    470                 *p++ = 0;
    471         }
    472 
    473         _vm->_system->setPalette(palette, 0, 256);
    474 }
    475 
    476479bool MoviePlayerSMK::processFrame() {
    477480        Graphics::Surface *screen = _vm->_system->lockScreen();
    478481        copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth);
    479482        _vm->_system->unlockScreen();
    480483
    481         uint32 waitTime = getFrameWaitTime();
     484        uint32 waitTime = getTimeToNextFrame();
    482485
    483         if (!waitTime) {
    484                 warning("dropped frame %i", getCurFrame());
    485                 return false;
    486         }
    487 
    488486        _vm->_system->updateScreen();
    489487
    490488        // Wait before showing the next frame
  • 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

     
    3030#include "common/list.h"
    3131#include "common/stream.h"
    3232
     33#include "graphics/surface.h"
     34#include "graphics/pixelformat.h"
     35
    3336namespace Common {
    3437        class SeekableReadStream;
    3538}
     
    4245class VideoDecoder {
    4346public:
    4447        VideoDecoder();
    45         virtual ~VideoDecoder();
     48        virtual ~VideoDecoder() {}
    4649
    4750        /**
    4851         * Returns the width of the video
    4952         * @return the width of the video
    5053         */
    51         virtual int getWidth();
     54        virtual uint16 getWidth() const = 0;
    5255
    5356        /**
    5457         * Returns the height of the video
    5558         * @return the height of the video
    5659         */
    57         virtual int getHeight();
     60        virtual uint16 getHeight() const = 0;
    5861
    5962        /**
    6063         * Returns the current frame number of the video
    61          * @return the current frame number of the video
     64         * @return the last frame decoded by the video
    6265         */
    63         virtual int32 getCurFrame();
     66        virtual int32 getCurFrame() const { return _curFrame; }
    6467
    6568        /**
    6669         * Returns the amount of frames in the video
    6770         * @return the amount of frames in the video
    6871         */
    69         virtual int32 getFrameCount();
     72        virtual uint32 getFrameCount() const = 0;
    7073
    7174        /**
    72          * Returns the frame rate of the video
    73          * @return the frame rate of the video
     75         * Returns the time (in ms) that the video has been running
    7476         */
    75         virtual int32 getFrameRate();
     77        virtual uint32 getElapsedTime() const;
    7678
    7779        /**
    78          * Returns the time to wait for each frame in 1/100 ms (to avoid rounding errors)
    79          * @return the time to wait for each frame in 1/100 ms (to avoid rounding errors)
     80         * Returns whether a frame should be decoded or not
     81         * @return whether a frame should be decoded or not
    8082         */
    81         virtual int32 getFrameDelay();
     83        virtual bool needsUpdate() const;
    8284
    8385        /**
    84          * Returns the current A/V lag in 1/100 ms (to avoid rounding errors)
    85          * If > 0, audio lags behind
    86          * If < 0, video lags behind
    87          * @return the current A/V lag in 1/100 ms (to avoid rounding errors)
     86         * Load a video file
     87         * @param filename      the filename to load
    8888         */
    89         virtual int32 getAudioLag();
     89        virtual bool loadFile(const Common::String &filename);
    9090
    9191        /**
    92          * Returns the time to wait until the next frame in ms, minding any lag
    93          * @return the time to wait until the next frame in ms
    94          */
    95         virtual uint32 getFrameWaitTime();
    96 
    97         /**
    9892         * Load a video file
    99          * @param filename      the filename to load
     93         * @param stream  the stream to load
    10094         */
    101         virtual bool loadFile(const char *filename) = 0;
     95        virtual bool load(Common::SeekableReadStream &stream) = 0;
    10296
    10397        /**
    10498         * Close a video file
    10599         */
    106         virtual void closeFile() = 0;
     100        virtual void close() = 0;
    107101
    108102        /**
    109103         * Returns if a video file is loaded or not
    110104         */
    111         bool isVideoLoaded() { return (_fileStream != NULL); }
     105        virtual bool isVideoLoaded() const = 0;
    112106
    113107        /**
    114          * Set RGB palette, based on current frame
    115          * @param pal           the RGB palette data
     108         * Decode the next frame and return the frame's surface
     109         * @note the return surface should *not* be freed
     110         * @note this may return 0, in which case the last frame should be kept on screen
    116111         */
    117         virtual void setPalette(byte *pal);
     112        virtual Surface *decodeNextFrame() = 0;
    118113
    119114        /**
    120          * Gets the value of the pixel at the specified x and y coordinates
    121          * Note: This method assumes that the video's pitch equals its width, and that
    122          * the video has an 8bpp palette
    123          * @param x     the x coordinate of the pixel
    124          * @param y     the y coordinate of the pixel
     115         * Get the pixel format of the video
    125116         */
    126         byte getPixel(int x, int y) {
    127                 return *(_videoFrameBuffer + y * _videoInfo.width + x * 1);
    128         }
     117        virtual PixelFormat getPixelFormat() const = 0;
    129118
    130119        /**
    131          * Gets the value of the pixel at the specified offset
    132          * @param offset        the offset of the pixel in the video buffer
     120         * Get the palette for the video in RGB format (if 8bpp or less)
    133121         */
    134         byte getPixel(int offset) { return getPixel(offset, 0); }
     122        virtual byte *getPalette() { return 0; }
    135123
    136124        /**
    137          * Return the black palette color for the current frame
     125         * Returns if the palette is dirty or not
    138126         */
    139         byte getBlack() { return _curFrameBlack; }
     127        virtual bool hasDirtyPalette() const { return false; }
    140128
    141129        /**
    142          * Return the white palette color for the current frame
     130         * Add the time the video has been paused to maintain sync
    143131         */
    144         byte getWhite() { return _curFrameWhite; }
     132        virtual void addPauseTime(uint32 ms) { _startTime += ms; }
    145133
    146134        /**
    147          * Copy current frame into the specified position of the destination
    148          * buffer.
    149          * @param dst           the buffer
    150          * @param x             the x position of the buffer
    151          * @param y             the y position of the buffer
    152          * @param pitch         the pitch of buffer
     135         * Returns if the video is finished or not
    153136         */
    154         void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
     137        virtual bool endOfVideo() const;
    155138
    156139        /**
    157          * Decode the next frame to _videoFrameBuffer
     140         * Set the current palette to the system palette
    158141         */
    159         virtual bool decodeNextFrame() = 0;
     142        void setSystemPalette();
    160143
     144        /**
     145         * Return the time until the next frame (in ms)
     146         */
     147        virtual uint32 getTimeToNextFrame() const = 0;
     148
    161149protected:
    162         struct {
    163                 uint32 width;
    164                 uint32 height;
    165                 uint32 frameCount;
    166                 int32 frameRate;
    167                 int32 frameDelay;               // 1/100 ms (to avoid rounding errors)
    168                 uint32 firstframeOffset;
    169                 uint32 currentFrame;
    170                 uint32 startTime;
    171         } _videoInfo;
     150        /**
     151         * Resets _curFrame and _startTime. Should be called from every close() function.
     152         */
     153        void reset();
    172154
    173         byte _curFrameBlack, _curFrameWhite;
    174 
    175         Common::SeekableReadStream *_fileStream;
    176         byte *_videoFrameBuffer;
     155        int32 _curFrame;
     156        uint32 _startTime;
    177157};
    178158
    179 class VideoPlayer {
     159/**
     160 * A VideoDecoder wrapper that implements getTimeToNextFrame() based on getFrameRate().
     161 */
     162class FixedRateVideoDecoder : public VideoDecoder {
    180163public:
    181         VideoPlayer(VideoDecoder* decoder) : _skipVideo(false), _decoder(decoder)
    182                 { }
    183         virtual ~VideoPlayer() { }
    184         /**
    185          * A default implementation of a video player
    186          * Plays a non-interactive full screen video till it's stopped by a
    187          * specific event
    188          * @param filename              the name of the file to play
    189          * @param stopEvents    a list of events that can stop the video
    190          *
    191          * Returns true if the video was played to the end, false if skipped
    192          */
    193         bool playVideo(Common::List<Common::Event> &stopEvents);
     164        FixedRateVideoDecoder() {}
     165        virtual ~FixedRateVideoDecoder() {}
    194166
    195         /**
    196          * Provides the same functionality as the video player, and it adds the
    197          * event of skipping the video with the escape key by default
    198          */
    199         bool playVideo();
     167        uint32 getTimeToNextFrame() const;
    200168
    201169protected:
    202170        /**
    203          * Perform postprocessing once the frame data is copied to the screen,
    204          * right before the frame is drawn. Called by playVideo()
     171         * Return the frame rate in frames per second
     172         * This returns a double because videos can have rates that are not integers and
     173         * there are some videos with frame rates < 1.
    205174         */
    206         virtual void performPostProcessing(byte *screen);
     175        virtual double getFrameRate() const = 0;
    207176
    208         bool _skipVideo;
    209         VideoDecoder* _decoder;
    210 
    211         void processVideoEvents(Common::List<Common::Event> &stopEvents);
     177private:
     178        uint32 getFrameBeginTime(uint32 frame) const;
    212179};
    213180
    214181} // End of namespace Graphics
  • 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 = 0;
    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(), (uint32)getFrameRate());
     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 = 0;
    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         if (_videoInfo.currentFrame == 0)
    488                 _videoInfo.startTime = g_system->getMillis();
    489 
    490         tag = _fileStream->readUint32BE();
     479Surface *DXADecoder::decodeNextFrame() {
     480        uint32 tag = _fileStream->readUint32BE();
    491481        if (tag == MKID_BE('CMAP')) {
    492                 byte rgb[768];
    493 
    494                 _fileStream->read(rgb, ARRAYSIZE(rgb));
    495                 setPalette(rgb);
     482                _fileStream->read(_palette, 256 * 3);
     483                _dirtyPalette = true;
    496484        }
    497485
    498486        tag = _fileStream->readUint32BE();
     
    529517
    530518                if (type == 3) {
    531519                        for (uint32 j = 0; j < _curHeight; ++j) {
    532                                 for (uint32 i = 0; i < _videoInfo.width; ++i) {
    533                                         const int offs = j * _videoInfo.width + i;
     520                                for (uint32 i = 0; i < _width; ++i) {
     521                                        const int offs = j * _width + i;
    534522                                        _frameBuffer1[offs] ^= _frameBuffer2[offs];
    535523                                }
    536524                        }
     
    540528        switch (_scaleMode) {
    541529        case S_INTERLACED:
    542530                for (int cy = 0; cy < _curHeight; cy++) {
    543                         memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
    544                         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);
    545533                }
    546                 _videoFrameBuffer = _scaledBuffer;
     534                _surface->pixels = _scaledBuffer;
    547535                break;
    548536        case S_DOUBLE:
    549537                for (int cy = 0; cy < _curHeight; cy++) {
    550                         memcpy(&_scaledBuffer[2 * cy * _videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);
    551                         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);
    552540                }
    553                 _videoFrameBuffer = _scaledBuffer;
     541                _surface->pixels = _scaledBuffer;
    554542                break;
    555543        case S_NONE:
    556                 _videoFrameBuffer = _frameBuffer1;
     544                _surface->pixels = _frameBuffer1;
    557545                break;
    558546        }
    559547
    560         return ++_videoInfo.currentFrame < _videoInfo.frameCount;
     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;
    561559}
    562560
    563561} // 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 = 0;
    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() {
    198         if (_videoInfo.currentFrame == 0)
    199                 _videoInfo.startTime = g_system->getMillis();
    200 
     198Surface *FlicDecoder::decodeNextFrame() {
    201199        // Read chunk
    202200        uint32 frameSize = _fileStream->readUint32LE();
    203201        uint16 frameType = _fileStream->readUint16LE();
    204202        uint16 chunkCount = 0;
    205203
    206204        switch (frameType) {
    207         case FRAME_TYPE: {
    208                 chunkCount = _fileStream->readUint16LE();
    209                 // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
    210                 // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here
    211                 uint16 newFrameDelay = _fileStream->readUint16LE();     // "speed", in milliseconds
    212                 if (newFrameDelay > 0) {
    213                         _videoInfo.frameDelay = 100 * newFrameDelay;
    214                         _videoInfo.frameRate = 100 * 1000 / _videoInfo.frameDelay;
    215                 }
    216                 _fileStream->readUint16LE();    // reserved, always 0
    217                 uint16 newWidth = _fileStream->readUint16LE();
    218                 uint16 newHeight = _fileStream->readUint16LE();
    219                 if (newWidth > 0)
    220                         _videoInfo.width = newWidth;
    221                 if (newHeight > 0)
    222                         _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.
    223209
    224                 _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;
     216
     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 == _videoInfo.frameCount + 1) {
    265                 _videoInfo.currentFrame = 1;
     275        if (_curFrame == (int32)_frameCount) {
     276                _curFrame = 0;
    266277                _fileStream->seek(_offsetFrame2);
    267278        }
    268279
    269         return _videoInfo.currentFrame < _videoInfo.frameCount;
     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"
     
    4746        _videoCodec = NULL;
    4847        _decodedHeader = false;
    4948        _audStream = NULL;
    50         _fileStream = NULL;
     49        _stream = NULL;
    5150        _audHandle = new Audio::SoundHandle();
     51        _dirtyPalette = false;
     52        _stream = NULL;
    5253        memset(_palette, 0, sizeof(_palette));
    5354        memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT));
    5455        memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER));
     
    5859}
    5960
    6061AviDecoder::~AviDecoder() {
    61         closeFile();
     62        close();
    6263        delete _audHandle;
    6364}
    6465
    6566void AviDecoder::runHandle(uint32 tag) {
    66         assert (_fileStream);
    67         if (_fileStream->eos())
     67        assert (_stream);
     68        if (_stream->eos())
    6869                return;
    6970
    7071        debug (3, "Decoding tag %s", tag2str(tag));
    7172
    7273        switch (tag) {
    7374                case ID_RIFF:
    74                         /*_filesize = */_fileStream->readUint32LE();
    75                         if (_fileStream->readUint32BE() != ID_AVI)
     75                        /*_filesize = */_stream->readUint32LE();
     76                        if (_stream->readUint32BE() != ID_AVI)
    7677                                error("RIFF file is not an AVI video");
    7778                        break;
    7879                case ID_LIST:
    7980                        handleList();
    8081                        break;
    8182                case ID_AVIH:
    82                         _header.size = _fileStream->readUint32LE();
    83                         _header.microSecondsPerFrame = _fileStream->readUint32LE();
    84                         _header.maxBytesPerSecond = _fileStream->readUint32LE();
    85                         _header.padding = _fileStream->readUint32LE();
    86                         _header.flags = _fileStream->readUint32LE();
    87                         _header.totalFrames = _fileStream->readUint32LE();
    88                         _header.initialFrames = _fileStream->readUint32LE();
    89                         _header.streams = _fileStream->readUint32LE();
    90                         _header.bufferSize = _fileStream->readUint32LE();
    91                         _header.width = _fileStream->readUint32LE();
    92                         _header.height = _fileStream->readUint32LE();
     83                        _header.size = _stream->readUint32LE();
     84                        _header.microSecondsPerFrame = _stream->readUint32LE();
     85                        _header.maxBytesPerSecond = _stream->readUint32LE();
     86                        _header.padding = _stream->readUint32LE();
     87                        _header.flags = _stream->readUint32LE();
     88                        _header.totalFrames = _stream->readUint32LE();
     89                        _header.initialFrames = _stream->readUint32LE();
     90                        _header.streams = _stream->readUint32LE();
     91                        _header.bufferSize = _stream->readUint32LE();
     92                        _header.width = _stream->readUint32LE();
     93                        _header.height = _stream->readUint32LE();
    9394                        //Ignore 16 bytes of reserved data
    94                         _fileStream->skip(16);
     95                        _stream->skip(16);
    9596                        break;
    9697                case ID_STRH:
    9798                        handleStreamHeader();
     
    100101                case ID_VEDT: // Unknown, safe to ignore
    101102                case ID_JUNK: // Alignment bytes, should be ignored
    102103                        {
    103                         uint32 junkSize = _fileStream->readUint32LE();
    104                         _fileStream->skip(junkSize + (junkSize & 1)); // Alignment
     104                        uint32 junkSize = _stream->readUint32LE();
     105                        _stream->skip(junkSize + (junkSize & 1)); // Alignment
    105106                        } break;
    106107                case ID_IDX1:
    107                         _ixInfo.size = _fileStream->readUint32LE();
     108                        _ixInfo.size = _stream->readUint32LE();
    108109                        _ixInfo.indices = new AVIOLDINDEX::Index[_ixInfo.size / 16];
    109110                        debug (0, "%d Indices", (_ixInfo.size / 16));
    110111                        for (uint32 i = 0; i < (_ixInfo.size / 16); i++) {
    111                                 _ixInfo.indices[i].id = _fileStream->readUint32BE();
    112                                 _ixInfo.indices[i].flags = _fileStream->readUint32LE();
    113                                 _ixInfo.indices[i].offset = _fileStream->readUint32LE();
    114                                 _ixInfo.indices[i].size = _fileStream->readUint32LE();
     112                                _ixInfo.indices[i].id = _stream->readUint32BE();
     113                                _ixInfo.indices[i].flags = _stream->readUint32LE();
     114                                _ixInfo.indices[i].offset = _stream->readUint32LE();
     115                                _ixInfo.indices[i].size = _stream->readUint32LE();
    115116                                debug (0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size);
    116117                        }
    117118                        break;
     
    121122}
    122123
    123124void AviDecoder::handleList() {
    124         uint32 listSize = _fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes
    125         uint32 listType = _fileStream->readUint32BE();
    126         uint32 curPos = _fileStream->pos();
     125        uint32 listSize = _stream->readUint32LE() - 4; // Subtract away listType's 4 bytes
     126        uint32 listType = _stream->readUint32BE();
     127        uint32 curPos = _stream->pos();
    127128
    128129        debug (0, "Found LIST of type %s", tag2str(listType));
    129130
    130         while ((_fileStream->pos() - curPos) < listSize)
    131                 runHandle(_fileStream->readUint32BE());
     131        while ((_stream->pos() - curPos) < listSize)
     132                runHandle(_stream->readUint32BE());
    132133
    133134        // We now have all the header data
    134135        if (listType == ID_HDRL)
     
    137138
    138139void AviDecoder::handleStreamHeader() {
    139140        AVIStreamHeader sHeader;
    140         sHeader.size = _fileStream->readUint32LE();
    141         sHeader.streamType = _fileStream->readUint32BE();
     141        sHeader.size = _stream->readUint32LE();
     142        sHeader.streamType = _stream->readUint32BE();
    142143        if (sHeader.streamType == ID_MIDS || sHeader.streamType == ID_TXTS)
    143144                error ("Unhandled MIDI/Text stream");
    144         sHeader.streamHandler = _fileStream->readUint32BE();
    145         sHeader.flags = _fileStream->readUint32LE();
    146         sHeader.priority = _fileStream->readUint16LE();
    147         sHeader.language = _fileStream->readUint16LE();
    148         sHeader.initialFrames = _fileStream->readUint32LE();
    149         sHeader.scale = _fileStream->readUint32LE();
    150         sHeader.rate = _fileStream->readUint32LE();
    151         sHeader.start = _fileStream->readUint32LE();
    152         sHeader.length = _fileStream->readUint32LE();
    153         sHeader.bufferSize = _fileStream->readUint32LE();
    154         sHeader.quality = _fileStream->readUint32LE();
    155         sHeader.sampleSize = _fileStream->readUint32LE();
    156         sHeader.frame.left = _fileStream->readSint16LE();
    157         sHeader.frame.top = _fileStream->readSint16LE();
    158         sHeader.frame.right = _fileStream->readSint16LE();
    159         sHeader.frame.bottom = _fileStream->readSint16LE();
     145        sHeader.streamHandler = _stream->readUint32BE();
     146        sHeader.flags = _stream->readUint32LE();
     147        sHeader.priority = _stream->readUint16LE();
     148        sHeader.language = _stream->readUint16LE();
     149        sHeader.initialFrames = _stream->readUint32LE();
     150        sHeader.scale = _stream->readUint32LE();
     151        sHeader.rate = _stream->readUint32LE();
     152        sHeader.start = _stream->readUint32LE();
     153        sHeader.length = _stream->readUint32LE();
     154        sHeader.bufferSize = _stream->readUint32LE();
     155        sHeader.quality = _stream->readUint32LE();
     156        sHeader.sampleSize = _stream->readUint32LE();
     157        sHeader.frame.left = _stream->readSint16LE();
     158        sHeader.frame.top = _stream->readSint16LE();
     159        sHeader.frame.right = _stream->readSint16LE();
     160        sHeader.frame.bottom = _stream->readSint16LE();
    160161
    161         if (_fileStream->readUint32BE() != ID_STRF)
     162        if (_stream->readUint32BE() != ID_STRF)
    162163                error("Could not find STRF tag");
    163         /* uint32 strfSize = */ _fileStream->readUint32LE();
     164        /* uint32 strfSize = */ _stream->readUint32LE();
    164165
    165166        if (sHeader.streamType == ID_VIDS) {
    166167                _vidsHeader = sHeader;
    167168
    168                 _bmInfo.size = _fileStream->readUint32LE();
    169                 _bmInfo.width = _fileStream->readUint32LE();
     169                _bmInfo.size = _stream->readUint32LE();
     170                _bmInfo.width = _stream->readUint32LE();
    170171                assert (_header.width == _bmInfo.width);
    171                 _bmInfo.height = _fileStream->readUint32LE();
     172                _bmInfo.height = _stream->readUint32LE();
    172173                assert (_header.height == _bmInfo.height);
    173                 _bmInfo.planes = _fileStream->readUint16LE();
    174                 _bmInfo.bitCount = _fileStream->readUint16LE();
    175                 _bmInfo.compression = _fileStream->readUint32BE();
    176                 _bmInfo.sizeImage = _fileStream->readUint32LE();
    177                 _bmInfo.xPelsPerMeter = _fileStream->readUint32LE();
    178                 _bmInfo.yPelsPerMeter = _fileStream->readUint32LE();
    179                 _bmInfo.clrUsed = _fileStream->readUint32LE();
    180                 _bmInfo.clrImportant = _fileStream->readUint32LE();
     174                _bmInfo.planes = _stream->readUint16LE();
     175                _bmInfo.bitCount = _stream->readUint16LE();
     176                _bmInfo.compression = _stream->readUint32BE();
     177                _bmInfo.sizeImage = _stream->readUint32LE();
     178                _bmInfo.xPelsPerMeter = _stream->readUint32LE();
     179                _bmInfo.yPelsPerMeter = _stream->readUint32LE();
     180                _bmInfo.clrUsed = _stream->readUint32LE();
     181                _bmInfo.clrImportant = _stream->readUint32LE();
    181182
    182183                if (_bmInfo.bitCount == 8) {
    183184                        if (_bmInfo.clrUsed == 0)
    184185                                _bmInfo.clrUsed = 256;
    185186
    186187                        for (uint32 i = 0; i < _bmInfo.clrUsed; i++) {
    187                                 _palette[i * 3 + 2] = _fileStream->readByte();
    188                                 _palette[i * 3 + 1] = _fileStream->readByte();
    189                                 _palette[i * 3] = _fileStream->readByte();
    190                                 /*_palette[i * 4 + 3] = */_fileStream->readByte();
     188                                _palette[i * 3 + 2] = _stream->readByte();
     189                                _palette[i * 3 + 1] = _stream->readByte();
     190                                _palette[i * 3] = _stream->readByte();
     191                                /*_palette[i * 4 + 3] = */_stream->readByte();
    191192                        }
    192193
    193                         setPalette(_palette);
     194                        _dirtyPalette = true;
    194195                }
    195196        } else if (sHeader.streamType == ID_AUDS) {
    196197                _audsHeader = sHeader;
    197198
    198                 _wvInfo.tag = _fileStream->readUint16LE();
    199                 _wvInfo.channels = _fileStream->readUint16LE();
    200                 _wvInfo.samplesPerSec = _fileStream->readUint32LE();
    201                 _wvInfo.avgBytesPerSec = _fileStream->readUint32LE();
    202                 _wvInfo.blockAlign = _fileStream->readUint16LE();
    203                 _wvInfo.size = _fileStream->readUint16LE();
     199                _wvInfo.tag = _stream->readUint16LE();
     200                _wvInfo.channels = _stream->readUint16LE();
     201                _wvInfo.samplesPerSec = _stream->readUint32LE();
     202                _wvInfo.avgBytesPerSec = _stream->readUint32LE();
     203                _wvInfo.blockAlign = _stream->readUint16LE();
     204                _wvInfo.size = _stream->readUint16LE();
    204205        }
    205206}
    206207
    207 bool AviDecoder::loadFile(const char *fileName) {
    208         closeFile();
     208bool AviDecoder::load(Common::SeekableReadStream &stream) {
     209        close();
    209210
    210         _fileStream = SearchMan.createReadStreamForMember(fileName);
    211         if (!_fileStream)
    212                 return false;
    213 
     211        _stream = &stream;
    214212        _decodedHeader = false;
    215         // Seek to the first frame
    216         _videoInfo.currentFrame = 0;
    217213
    218 
    219214        // Read chunks until we have decoded the header
    220215        while (!_decodedHeader)
    221                 runHandle(_fileStream->readUint32BE());
     216                runHandle(_stream->readUint32BE());
    222217
    223         _videoFrameBuffer = new byte[_header.width * _header.height];
    224         memset(_videoFrameBuffer, 0, _header.width * _header.height);
     218        uint32 nextTag = _stream->readUint32BE();
    225219
    226         uint32 nextTag = _fileStream->readUint32BE();
    227 
    228220        // Throw out any JUNK section
    229221        if (nextTag == ID_JUNK) {
    230222                runHandle(ID_JUNK);
    231                 nextTag = _fileStream->readUint32BE();
     223                nextTag = _stream->readUint32BE();
    232224        }
    233225
    234226        // Ignore the 'movi' LIST
    235227        if (nextTag == ID_LIST) {
    236                 _fileStream->readUint32BE(); // Skip size
    237                 if (_fileStream->readUint32BE() != ID_MOVI)
     228                _stream->readUint32BE(); // Skip size
     229                if (_stream->readUint32BE() != ID_MOVI)
    238230                        error ("Expected 'movi' LIST");
    239231        } else
    240232                error ("Expected 'movi' LIST");
     
    248240                _mixer->playInputStream(_soundType, _audHandle, _audStream);
    249241
    250242        debug (0, "Frames = %d, Dimensions = %d x %d", _header.totalFrames, _header.width, _header.height);
    251         debug (0, "Frame Rate = %d", getFrameRate());
     243        debug (0, "Frame Rate = %d", _vidsHeader.rate / _vidsHeader.scale);
    252244        if ((_audsHeader.scale != 0) && (_header.flags & AVIF_ISINTERLEAVED))
    253245                debug (0, "Sound Rate = %d", AUDIO_RATE);
    254246        debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler));
    255247
    256         _videoInfo.firstframeOffset = _fileStream->pos();
    257         _videoInfo.width = _header.width;
    258         _videoInfo.height = _header.height;
    259         _videoInfo.frameCount = _header.totalFrames;
    260         // Our frameDelay is calculated in 1/100 ms, so we convert it here
    261         _videoInfo.frameDelay = _header.microSecondsPerFrame / 10;
    262 
    263248        if (!_videoCodec)
    264249                return false;
    265250
    266251        return true;
    267252}
    268253
    269 void AviDecoder::closeFile() {
    270         if (!_fileStream)
     254void AviDecoder::close() {
     255        if (!_stream)
    271256                return;
    272257
    273         delete _fileStream;
    274         _fileStream = 0;
     258        delete _stream;
     259        _stream = 0;
    275260
    276         delete[] _videoFrameBuffer;
    277         _videoFrameBuffer = 0;
    278 
    279261        // Deinitialize sound
    280262        _mixer->stopHandle(*_audHandle);
    281263        _audStream = 0;
     
    294276        memset(&_vidsHeader, 0, sizeof(AVIStreamHeader));
    295277        memset(&_audsHeader, 0, sizeof(AVIStreamHeader));
    296278        memset(&_ixInfo, 0, sizeof(AVIOLDINDEX));
     279
     280        reset();
    297281}
    298282
    299 Surface *AviDecoder::getNextFrame() {
    300         uint32 nextTag = _fileStream->readUint32BE();
     283uint32 AviDecoder::getElapsedTime() const {
     284        if (_audStream)
     285                return _mixer->getSoundElapsedTime(*_audHandle);
    301286
    302         if (_fileStream->eos())
     287        return VideoDecoder::getElapsedTime();
     288}
     289
     290Surface *AviDecoder::decodeNextFrame() {
     291        uint32 nextTag = _stream->readUint32BE();
     292
     293        if (_stream->eos())
    303294                return NULL;
    304295
     296        if (_curFrame == -1)
     297                _startTime = g_system->getMillis();
     298
    305299        if (nextTag == ID_LIST) {
    306300                // A list of audio/video chunks
    307                 uint32 listSize = _fileStream->readUint32LE() - 4;
    308                 int32 startPos = _fileStream->pos();
     301                uint32 listSize = _stream->readUint32LE() - 4;
     302                int32 startPos = _stream->pos();
    309303
    310                 if (_fileStream->readUint32BE() != ID_REC)
     304                if (_stream->readUint32BE() != ID_REC)
    311305                        error ("Expected 'rec ' LIST");
    312306
    313307                // Decode chunks in the list and see if we get a frame
    314308                Surface *frame = NULL;
    315                 while (_fileStream->pos() < startPos + (int32)listSize) {
    316                         Surface *temp = getNextFrame();
     309                while (_stream->pos() < startPos + (int32)listSize) {
     310                        Surface *temp = decodeNextFrame();
    317311                        if (temp)
    318312                                frame = temp;
    319313                }
     
    321315                return frame;
    322316        } else if (getStreamType(nextTag) == 'wb') {
    323317                // Audio Chunk
    324                 uint32 chunkSize = _fileStream->readUint32LE();
     318                uint32 chunkSize = _stream->readUint32LE();
    325319                byte *data = (byte *)malloc(chunkSize);
    326                 _fileStream->read(data, chunkSize);
     320                _stream->read(data, chunkSize);
    327321
    328322                byte flags = 0;
    329323                if (_audsHeader.sampleSize == 2)
     
    332326                        flags |= Audio::FLAG_UNSIGNED;
    333327
    334328                _audStream->queueBuffer(data, chunkSize, DisposeAfterUse::YES, flags);
    335                 _fileStream->skip(chunkSize & 1); // Alignment
     329                _stream->skip(chunkSize & 1); // Alignment
    336330        } else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' ||
    337331                   getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32') {
    338332                // Compressed Frame
    339                 _videoInfo.currentFrame++;
    340                 uint32 chunkSize = _fileStream->readUint32LE();
     333                _curFrame++;
     334                uint32 chunkSize = _stream->readUint32LE();
    341335
    342336                if (chunkSize == 0) // Keep last frame on screen
    343337                        return NULL;
    344338
    345                 Common::SeekableReadStream *frameData = _fileStream->readStream(chunkSize);
     339                Common::SeekableReadStream *frameData = _stream->readStream(chunkSize);
    346340                Graphics::Surface *surface = _videoCodec->decodeImage(frameData);
    347341                delete frameData;
    348                 _fileStream->skip(chunkSize & 1); // Alignment
     342                _stream->skip(chunkSize & 1); // Alignment
    349343                return surface;
    350344        } else if (getStreamType(nextTag) == 'pc') {
    351345                // Palette Change
    352                 _fileStream->readUint32LE(); // Chunk size, not needed here
    353                 byte firstEntry = _fileStream->readByte();
    354                 uint16 numEntries = _fileStream->readByte();
    355                 _fileStream->readUint16LE(); // Reserved
     346                _stream->readUint32LE(); // Chunk size, not needed here
     347                byte firstEntry = _stream->readByte();
     348                uint16 numEntries = _stream->readByte();
     349                _stream->readUint16LE(); // Reserved
    356350
    357351                // 0 entries means all colors are going to be changed
    358352                if (numEntries == 0)
    359353                        numEntries = 256;
    360354
    361355                for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) {
    362                         _palette[i * 3] = _fileStream->readByte();
    363                         _palette[i * 3 + 1] = _fileStream->readByte();
    364                         _palette[i * 3 + 2] = _fileStream->readByte();
    365                         _fileStream->readByte(); // Flags that don't serve us any purpose
     356                        _palette[i * 3] = _stream->readByte();
     357                        _palette[i * 3 + 1] = _stream->readByte();
     358                        _palette[i * 3 + 2] = _stream->readByte();
     359                        _stream->readByte(); // Flags that don't serve us any purpose
    366360                }
    367361
    368                 setPalette(_palette);
     362                _dirtyPalette = true;
    369363
    370364                // No alignment necessary. It's always even.
    371365        } else if (nextTag == ID_JUNK) {
     
    373367        } else if (nextTag == ID_IDX1) {
    374368                runHandle(ID_IDX1);
    375369        } else
    376                 error ("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());
     370                error("Tag = \'%s\', %d", tag2str(nextTag), _stream->pos());
    377371
    378372        return NULL;
    379373}
    380374
    381 bool AviDecoder::decodeNextFrame() {
    382         if (_videoInfo.currentFrame == 0)
    383                 _videoInfo.startTime = g_system->getMillis();
    384 
    385         Surface *surface = NULL;
    386 
    387         uint32 curFrame = _videoInfo.currentFrame;
    388 
    389         while (!surface && _videoInfo.currentFrame < _videoInfo.frameCount && !_fileStream->eos())
    390                 surface = getNextFrame();
    391 
    392         if (curFrame == _videoInfo.currentFrame) {
    393                 warning("No video frame found");
    394                 _videoInfo.currentFrame++;
    395         }
    396 
    397         if (surface)
    398                 memcpy(_videoFrameBuffer, surface->pixels, _header.width * _header.height);
    399 
    400         return _videoInfo.currentFrame < _videoInfo.frameCount;
    401 }
    402 
    403 int32 AviDecoder::getAudioLag() {
    404         if (!_fileStream)
    405                 return 0;
    406 
    407         int32 frameDelay = getFrameDelay();
    408         int32 videoTime = _videoInfo.currentFrame * frameDelay;
    409         int32 audioTime;
    410 
    411         if (!_audStream) {
    412                 /* No audio.
    413                    Calculate the lag by how much time has gone by since the first frame
    414                    and how much time *should* have passed.
    415                 */
    416 
    417                 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
    418         } else {
    419                 const Audio::Timestamp ts = _mixer->getElapsedTime(*_audHandle);
    420                 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();
    421         }
    422 
    423         return videoTime - audioTime;
    424 }
    425 
    426375Codec *AviDecoder::createCodec() {
    427376        switch (_vidsHeader.streamHandler) {
    428377                case ID_CRAM:
     
    438387        return NULL;
    439388}
    440389
    441 Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
     390PixelFormat AviDecoder::getPixelFormat() const {
     391        assert(_videoCodec);
     392        return _videoCodec->getPixelFormat();
     393}
    442394
    443         if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) {
     395Audio::QueuingAudioStream *AviDecoder::createAudioStream() {
     396        if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM)
    444397                return Audio::makeQueuingAudioStream(AUDIO_RATE, false);
    445         }
    446398
    447399        if (_wvInfo.tag != 0) // No sound
    448400                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        double 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_FLIC_DECODER_H
     27#define GRAPHICS_VIDEO_FLIC_DECODER_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
    50         /**
    51          * Load a FLIC encoded video file
    52          * @param filename      the filename to load
    53          */
    54         bool loadFile(const char *fileName);
     50        bool load(Common::SeekableReadStream &stream);
     51        void close();
    5552
    56         /**
    57          * Close a FLIC encoded video file
    58          */
    59         void closeFile();
     53        bool isVideoLoaded() const { return _fileStream != 0; }
     54        uint16 getWidth() const { return _surface->w; }
     55        uint16 getHeight() const { return _surface->h; }
     56        uint32 getFrameCount() const { return _frameCount; }
     57        Surface *decodeNextFrame();
     58        PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); }
    6059
    61         /**
    62          * Decode the next frame
    63          */
    64         bool decodeNextFrame();
    65 
    6660        const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; }
    6761        void clearDirtyRects() { _dirtyRects.clear(); }
    6862        void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
    6963
    70         const byte *getPalette() { _paletteChanged = false; return _palette; }
    71         bool paletteChanged() { return _paletteChanged; }
     64        byte *getPalette() { _paletteChanged = false; return _palette; }
     65        bool hasDirtyPalette() { return _paletteChanged; }
    7266        void reset();
    7367
     68protected:
     69        double getFrameRate() const { return _frameRate; }
     70
    7471private:
    7572        uint16 _offsetFrame1;
    7673        uint16 _offsetFrame2;
     
    8178        void decodeDeltaFLC(uint8 *data);
    8279        void unpackPalette(uint8 *mem);
    8380
     81        Common::SeekableReadStream *_fileStream;
     82        Surface *_surface;
     83        uint32 _frameCount;
     84        uint32 _frameRate;
     85
    8486        Common::List<Common::Rect> _dirtyRects;
    85 
    8687};
    8788
    8889} // 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 _stream != 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        double getFrameRate() const { return (double)_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 *_stream;
    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 * 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 = 0;
    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);
     467        _surface = new Graphics::Surface();
     468        _surface->create(width, height * (_header.flags ? 2 : 1), 1);
    499469        _palette = (byte *)malloc(3 * 256);
    500470        memset(_palette, 0, 3 * 256);
    501 
    502         _videoInfo.firstframeOffset = _fileStream->pos();
    503 
    504471        return true;
    505472}
    506473
    507 void SmackerDecoder::closeFile() {
     474void SmackerDecoder::close() {
    508475        if (!_fileStream)
    509476                return;
    510477
     
    517484        delete _fileStream;
    518485        _fileStream = 0;
    519486
     487        _surface->free();
     488        delete _surface;
     489        _surface = 0;
     490
    520491        delete _MMapTree;
    521492        delete _MClrTree;
    522493        delete _FullTree;
    523494        delete _TypeTree;
    524495
    525         free(_frameSizes);
    526         free(_frameTypes);
    527         free(_videoFrameBuffer);
     496        delete[] _frameSizes;
     497        delete[] _frameTypes;
    528498        free(_palette);
     499
     500        reset();
    529501}
    530502
    531 bool SmackerDecoder::decodeNextFrame() {
     503Surface *SmackerDecoder::decodeNextFrame() {
    532504        uint i;
    533505        uint32 chunkSize = 0;
    534506        uint32 dataSizeUnpacked = 0;
    535507
    536508        uint32 startPos = _fileStream->pos();
    537509
    538         if (_videoInfo.currentFrame == 0)
    539                 _videoInfo.startTime = g_system->getMillis();
     510        _curFrame++;
    540511
    541512        // Check if we got a frame with palette data, and
    542513        // call back the virtual setPalette function to set
    543514        // the current palette
    544         if (_frameTypes[_videoInfo.currentFrame] & 1) {
     515        if (_frameTypes[_curFrame] & 1) {
    545516                unpackPalette();
    546                 setPalette(_palette);
     517                _dirtyPalette = true;
    547518        }
    548519
    549520        // Load audio tracks
    550521        for (i = 0; i < 7; ++i) {
    551                 if (!(_frameTypes[_videoInfo.currentFrame] & (2 << i)))
     522                if (!(_frameTypes[_curFrame] & (2 << i)))
    552523                        continue;
    553524
    554525                chunkSize = _fileStream->readUint32LE();
     
    596567                }
    597568        }
    598569
    599         uint32 frameSize = _frameSizes[_videoInfo.currentFrame] & ~3;
     570        uint32 frameSize = _frameSizes[_curFrame] & ~3;
    600571
    601572        if (_fileStream->pos() - startPos > frameSize)
    602                 exit(1);
     573                error("Smacker actual frame size exceeds recorded frame size");
    603574
    604575        uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos);
    605576
     
    613584        _FullTree->reset();
    614585        _TypeTree->reset();
    615586
    616         uint bw = _videoInfo.width / 4;
    617         uint bh = _videoInfo.height / 4;
    618         uint stride = _videoInfo.width;
     587        uint bw = getWidth() / 4;
     588        uint bh = getHeight() / (_header.flags ? 2 : 1) / 4;
     589        uint stride = getWidth();
    619590        uint block = 0, blocks = bw*bh;
    620591
    621592        uint doubleY = _header.flags ? 2 : 1;
     
    634605                        while (run-- && block < blocks) {
    635606                                clr = _MClrTree->getCode(bs);
    636607                                map = _MMapTree->getCode(bs);
    637                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     608                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    638609                                hi = clr >> 8;
    639610                                lo = clr & 0xff;
    640611                                for (i = 0; i < 4; i++) {
     
    667638                        }
    668639
    669640                        while (run-- && block < blocks) {
    670                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     641                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    671642                                switch (mode) {
    672643                                        case 0:
    673644                                                for (i = 0; i < 4; ++i) {
     
    733704                        uint32 col;
    734705                        mode = type >> 8;
    735706                        while (run-- && block < blocks) {
    736                                 out = _videoFrameBuffer + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
     707                                out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;
    737708                                col = mode * 0x01010101;
    738709                                for (i = 0; i < 4 * doubleY; ++i) {
    739710                                        out[0] = out[1] = out[2] = out[3] = col;
     
    749720
    750721        free(_frameData);
    751722
    752         return ++_videoInfo.currentFrame < _videoInfo.frameCount;
     723        if (_curFrame == 0)
     724                _startTime = g_system->getMillis();
     725
     726        return _surface;
    753727}
    754728
    755729void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize,
     
    804778                // If the sample is stereo, the data is stored for the left and right channel, respectively
    805779                // (the exact opposite to the base values)
    806780                if (!is16Bits) {
    807 
    808781                        for (int k = 0; k < (isStereo ? 2 : 1); k++) {
    809782                                bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS));
    810783                                *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80;
    811784                                curPos++;
    812785                        }
    813 
    814786                } else {
    815 
    816787                        for (int k = 0; k < (isStereo ? 2 : 1); k++) {
    817788                                bases[k] += (int16) (audioTrees[k * 2]->getCode(audioBS) |
    818789                                                    (audioTrees[k * 2 + 1]->getCode(audioBS) << 8));
     
    885856        }
    886857
    887858        _fileStream->seek(startPos + len);
    888 
    889859        free(chunk);
    890860}
    891861
  • graphics/video/video_player.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$
    22  * $Id$
    23  *
    24  */
    25 
    26 #include "common/archive.h"
    27 #include "common/debug.h"
    28 #include "common/events.h"
    29 #include "common/system.h"
    30 #include "common/util.h"
    31 #include "common/array.h"
    32 #include "common/endian.h"
    33 
    34 #include "graphics/video/video_player.h"
    35 #include "graphics/surface.h"
    36 
    37 namespace Graphics {
    38 
    39 VideoDecoder::VideoDecoder() : _fileStream(0) {
    40         _curFrameBlack = 0;
    41         _curFrameWhite = 255;
    42 }
    43 
    44 VideoDecoder::~VideoDecoder() {
    45 }
    46 
    47 int VideoDecoder::getWidth() {
    48         if (!_fileStream)
    49                 return 0;
    50         return _videoInfo.width;
    51 }
    52 
    53 int VideoDecoder::getHeight() {
    54         if (!_fileStream)
    55                 return 0;
    56         return _videoInfo.height;
    57 }
    58 
    59 int32 VideoDecoder::getCurFrame() {
    60         if (!_fileStream)
    61                 return -1;
    62         return _videoInfo.currentFrame;
    63 }
    64 
    65 int32 VideoDecoder::getFrameCount() {
    66         if (!_fileStream)
    67                 return 0;
    68         return _videoInfo.frameCount;
    69 }
    70 
    71 int32 VideoDecoder::getFrameRate() {
    72         if (!_fileStream)
    73                 return 0;
    74         return _videoInfo.frameRate;
    75 }
    76 
    77 int32 VideoDecoder::getFrameDelay() {
    78         if (!_fileStream)
    79                 return 0;
    80         return _videoInfo.frameDelay;
    81 }
    82 
    83 int32 VideoDecoder::getAudioLag() {
    84         if (!_fileStream)
    85                 return 0;
    86 
    87         /* No audio.
    88            Calculate the lag by how much time has gone by since the first frame
    89            and how much time *should* have passed.
    90         */
    91         int32 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
    92         int32 videoTime = _videoInfo.currentFrame * getFrameDelay();
    93 
    94         return videoTime - audioTime;
    95 }
    96 
    97 uint32 VideoDecoder::getFrameWaitTime() {
    98         int32 waitTime = (getFrameDelay() + getAudioLag()) / 100;
    99 
    100         if (waitTime < 0)
    101                 return 0;
    102 
    103         return waitTime;
    104 }
    105 
    106 void VideoDecoder::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
    107         uint h = getHeight();
    108         uint w = getWidth();
    109 
    110         byte *src = _videoFrameBuffer;
    111         dst += y * pitch + x;
    112 
    113         do {
    114                 memcpy(dst, src, w);
    115                 dst += pitch;
    116                 src += w;
    117         } while (--h);
    118 }
    119 
    120 void VideoDecoder::setPalette(byte *pal) {
    121         byte videoPalette[256 * 4];
    122 
    123         uint32 maxWeight = 0;
    124         uint32 minWeight = 0xFFFFFFFF;
    125         uint32 weight = 0;
    126         byte r, g, b;
    127 
    128         for (int i = 0; i < 256; i++) {
    129                 videoPalette[i * 4 + 0] = *pal++;
    130                 videoPalette[i * 4 + 1] = *pal++;
    131                 videoPalette[i * 4 + 2] = *pal++;
    132                 videoPalette[i * 4 + 3] = 0;
    133 
    134                 // Try and find the white and black colors for the current palette
    135                 r = videoPalette[i * 4 + 0];
    136                 g = videoPalette[i * 4 + 1];
    137                 b = videoPalette[i * 4 + 2];
    138 
    139                 weight = 3 * r * r + 6 * g * g + 2 * b * b;
    140 
    141                 if (weight >= maxWeight) {
    142                         _curFrameWhite = i;
    143                         maxWeight = weight;
    144                 }
    145 
    146                 if (weight <= minWeight) {
    147                         _curFrameBlack = i;
    148                         minWeight = i;
    149                 }
    150         }
    151 
    152         g_system->setPalette(videoPalette, 0, 256);
    153 }
    154 
    155 
    156 /*
    157  *  VideoPlayer
    158  */
    159 
    160 void VideoPlayer::processVideoEvents(Common::List<Common::Event> &stopEvents) {
    161         Common::Event curEvent;
    162         Common::EventManager *eventMan = g_system->getEventManager();
    163 
    164         // Process events, and skip video if esc is pressed
    165         while (eventMan->pollEvent(curEvent)) {
    166                 if (curEvent.type == Common::EVENT_RTL || curEvent.type == Common::EVENT_QUIT) {
    167                         _skipVideo = true;
    168                 }
    169 
    170                 for (Common::List<Common::Event>::const_iterator iter = stopEvents.begin(); iter != stopEvents.end(); ++iter) {
    171                         if (curEvent.type == iter->type) {
    172                                 if (iter->type == Common::EVENT_KEYDOWN || iter->type == Common::EVENT_KEYUP) {
    173                                         if (curEvent.kbd.keycode == iter->kbd.keycode) {
    174                                                 _skipVideo = true;
    175                                                 break;
    176                                         }
    177                                 } else {
    178                                         _skipVideo = true;
    179                                         break;
    180                                 }
    181                         }
    182                 }
    183         }
    184 }
    185 
    186 bool VideoPlayer::playVideo(Common::List<Common::Event> &stopEvents) {
    187         _skipVideo = false;
    188         debug(0, "Playing video");
    189 
    190         g_system->fillScreen(0);
    191 
    192         int frameX = (g_system->getWidth() - _decoder->getWidth()) / 2;
    193         int frameY = (g_system->getHeight() - _decoder->getHeight()) / 2;
    194 
    195         while (_decoder->getCurFrame() < _decoder->getFrameCount() && !_skipVideo) {
    196                 processVideoEvents(stopEvents);
    197 
    198                 uint32 startTime = 0;
    199                 _decoder->decodeNextFrame();
    200 
    201                 Graphics::Surface *screen = g_system->lockScreen();
    202                 _decoder->copyFrameToBuffer((byte *)screen->pixels, frameX, frameY, g_system->getWidth());
    203                 performPostProcessing((byte *)screen->pixels);
    204                 g_system->unlockScreen();
    205 
    206                 uint32 waitTime = _decoder->getFrameWaitTime();
    207 
    208                 if (!waitTime) {
    209                         warning("dropped frame %i", _decoder->getCurFrame());
    210                         continue;
    211                 }
    212 
    213                 // Update the screen
    214                 g_system->updateScreen();
    215 
    216                 startTime = g_system->getMillis();
    217 
    218                 // Wait before showing the next frame
    219                 while (g_system->getMillis() < startTime + waitTime && !_skipVideo) {
    220                         processVideoEvents(stopEvents);
    221                         g_system->delayMillis(10);
    222                 }
    223         }
    224 
    225         return !_skipVideo;
    226 }
    227 
    228 bool VideoPlayer::playVideo() {
    229         Common::Event stopEvent;
    230         Common::List<Common::Event> stopEvents;
    231         stopEvents.clear();
    232         stopEvent.type = Common::EVENT_KEYDOWN;
    233         stopEvent.kbd = Common::KEYCODE_ESCAPE;
    234         stopEvents.push_back(stopEvent);
    235 
    236         return playVideo(stopEvents);
    237 }
    238 
    239 void VideoPlayer::performPostProcessing(byte *screen) {
    240 }
    241 
    242 } // End of namespace Graphics
  • 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        double 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_player.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$
    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/stream.h"
    32 
    33 namespace Common {
    34         class SeekableReadStream;
    35 }
    36 
    37 namespace Graphics {
    38 
    39 /**
    40  * Implementation of a generic video decoder
    41  */
    42 class VideoDecoder {
    43 public:
    44         VideoDecoder();
    45         virtual ~VideoDecoder();
    46 
    47         /**
    48          * Returns the width of the video
    49          * @return the width of the video
    50          */
    51         virtual int getWidth();
    52 
    53         /**
    54          * Returns the height of the video
    55          * @return the height of the video
    56          */
    57         virtual int getHeight();
    58 
    59         /**
    60          * Returns the current frame number of the video
    61          * @return the current frame number of the video
    62          */
    63         virtual int32 getCurFrame();
    64 
    65         /**
    66          * Returns the amount of frames in the video
    67          * @return the amount of frames in the video
    68          */
    69         virtual int32 getFrameCount();
    70 
    71         /**
    72          * Returns the frame rate of the video
    73          * @return the frame rate of the video
    74          */
    75         virtual int32 getFrameRate();
    76 
    77         /**
    78          * Returns the time to wait for each frame in 1/100 ms (to avoid rounding errors)
    79          * @return the time to wait for each frame in 1/100 ms (to avoid rounding errors)
    80          */
    81         virtual int32 getFrameDelay();
    82 
    83         /**
    84          * Returns the current A/V lag in 1/100 ms (to avoid rounding errors)
    85          * If > 0, audio lags behind
    86          * If < 0, video lags behind
    87          * @return the current A/V lag in 1/100 ms (to avoid rounding errors)
    88          */
    89         virtual int32 getAudioLag();
    90 
    91         /**
    92          * Returns the time to wait until the next frame in ms, minding any lag
    93          * @return the time to wait until the next frame in ms
    94          */
    95         virtual uint32 getFrameWaitTime();
    96 
    97         /**
    98          * Load a video file
    99          * @param filename      the filename to load
    100          */
    101         virtual bool loadFile(const char *filename) = 0;
    102 
    103         /**
    104          * Close a video file
    105          */
    106         virtual void closeFile() = 0;
    107 
    108         /**
    109          * Returns if a video file is loaded or not
    110          */
    111         bool isVideoLoaded() { return (_fileStream != NULL); }
    112 
    113         /**
    114          * Set RGB palette, based on current frame
    115          * @param pal           the RGB palette data
    116          */
    117         virtual void setPalette(byte *pal);
    118 
    119         /**
    120          * Gets the value of the pixel at the specified x and y coordinates
    121          * Note: This method assumes that the video's pitch equals its width, and that
    122          * the video has an 8bpp palette
    123          * @param x     the x coordinate of the pixel
    124          * @param y     the y coordinate of the pixel
    125          */
    126         byte getPixel(int x, int y) {
    127                 return *(_videoFrameBuffer + y * _videoInfo.width + x * 1);
    128         }
    129 
    130         /**
    131          * Gets the value of the pixel at the specified offset
    132          * @param offset        the offset of the pixel in the video buffer
    133          */
    134         byte getPixel(int offset) { return getPixel(offset, 0); }
    135 
    136         /**
    137          * Return the black palette color for the current frame
    138          */
    139         byte getBlack() { return _curFrameBlack; }
    140 
    141         /**
    142          * Return the white palette color for the current frame
    143          */
    144         byte getWhite() { return _curFrameWhite; }
    145 
    146         /**
    147          * Copy current frame into the specified position of the destination
    148          * buffer.
    149          * @param dst           the buffer
    150          * @param x             the x position of the buffer
    151          * @param y             the y position of the buffer
    152          * @param pitch         the pitch of buffer
    153          */
    154         void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);
    155 
    156         /**
    157          * Decode the next frame to _videoFrameBuffer
    158          */
    159         virtual bool decodeNextFrame() = 0;
    160 
    161 protected:
    162         struct {
    163                 uint32 width;
    164                 uint32 height;
    165                 uint32 frameCount;
    166                 int32 frameRate;
    167                 int32 frameDelay;               // 1/100 ms (to avoid rounding errors)
    168                 uint32 firstframeOffset;
    169                 uint32 currentFrame;
    170                 uint32 startTime;
    171         } _videoInfo;
    172 
    173         byte _curFrameBlack, _curFrameWhite;
    174 
    175         Common::SeekableReadStream *_fileStream;
    176         byte *_videoFrameBuffer;
    177 };
    178 
    179 class VideoPlayer {
    180 public:
    181         VideoPlayer(VideoDecoder* decoder) : _skipVideo(false), _decoder(decoder)
    182                 { }
    183         virtual ~VideoPlayer() { }
    184         /**
    185          * A default implementation of a video player
    186          * Plays a non-interactive full screen video till it's stopped by a
    187          * specific event
    188          * @param filename              the name of the file to play
    189          * @param stopEvents    a list of events that can stop the video
    190          *
    191          * Returns true if the video was played to the end, false if skipped
    192          */
    193         bool playVideo(Common::List<Common::Event> &stopEvents);
    194 
    195         /**
    196          * Provides the same functionality as the video player, and it adds the
    197          * event of skipping the video with the escape key by default
    198          */
    199         bool playVideo();
    200 
    201 protected:
    202         /**
    203          * Perform postprocessing once the frame data is copied to the screen,
    204          * right before the frame is drawn. Called by playVideo()
    205          */
    206         virtual void performPostProcessing(byte *screen);
    207 
    208         bool _skipVideo;
    209         VideoDecoder* _decoder;
    210 
    211         void processVideoEvents(Common::List<Common::Event> &stopEvents);
    212 };
    213 
    214 } // End of namespace Graphics
    215 
    216 #endif
  • graphics/video/video_decoder.cpp

     
    2323 *
    2424 */
    2525
    26 #include "common/archive.h"
    27 #include "common/debug.h"
    28 #include "common/events.h"
     26#include "graphics/video/video_decoder.h"
     27
     28#include "common/file.h"
    2929#include "common/system.h"
    30 #include "common/util.h"
    31 #include "common/array.h"
    32 #include "common/endian.h"
    3330
    34 #include "graphics/video/video_player.h"
    35 #include "graphics/surface.h"
    36 
    3731namespace Graphics {
    3832
    39 VideoDecoder::VideoDecoder() : _fileStream(0) {
    40         _curFrameBlack = 0;
    41         _curFrameWhite = 255;
     33VideoDecoder::VideoDecoder() {
     34        reset();
    4235}
    4336
    44 VideoDecoder::~VideoDecoder() {
    45 }
     37bool VideoDecoder::loadFile(const Common::String &filename) {
     38        Common::File *file = new Common::File();
    4639
    47 int VideoDecoder::getWidth() {
    48         if (!_fileStream)
    49                 return 0;
    50         return _videoInfo.width;
    51 }
     40        if (!file->open(filename)) {
     41                delete file;
     42                return false;
     43        }
    5244
    53 int VideoDecoder::getHeight() {
    54         if (!_fileStream)
    55                 return 0;
    56         return _videoInfo.height;
     45        return load(*file);
    5746}
    5847
    59 int32 VideoDecoder::getCurFrame() {
    60         if (!_fileStream)
    61                 return -1;
    62         return _videoInfo.currentFrame;
     48uint32 VideoDecoder::getElapsedTime() const {
     49        return g_system->getMillis() - _startTime;
    6350}
    6451
    65 int32 VideoDecoder::getFrameCount() {
    66         if (!_fileStream)
    67                 return 0;
    68         return _videoInfo.frameCount;
    69 }
     52void VideoDecoder::setSystemPalette() {
     53        byte *vidPalette = getPalette();
     54        byte *sysPalette = new byte[256 * 4];
    7055
    71 int32 VideoDecoder::getFrameRate() {
    72         if (!_fileStream)
    73                 return 0;
    74         return _videoInfo.frameRate;
    75 }
     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        }
    7662
    77 int32 VideoDecoder::getFrameDelay() {
    78         if (!_fileStream)
    79                 return 0;
    80         return _videoInfo.frameDelay;
     63        g_system->setPalette(sysPalette, 0, 256);
     64        delete[] sysPalette;
    8165}
    8266
    83 int32 VideoDecoder::getAudioLag() {
    84         if (!_fileStream)
    85                 return 0;
    86 
    87         /* No audio.
    88            Calculate the lag by how much time has gone by since the first frame
    89            and how much time *should* have passed.
    90         */
    91         int32 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;
    92         int32 videoTime = _videoInfo.currentFrame * getFrameDelay();
    93 
    94         return videoTime - audioTime;
     67bool VideoDecoder::needsUpdate() const {       
     68        return !endOfVideo() && getTimeToNextFrame() == 0;
    9569}
    9670
    97 uint32 VideoDecoder::getFrameWaitTime() {
    98         int32 waitTime = (getFrameDelay() + getAudioLag()) / 100;
    99 
    100         if (waitTime < 0)
    101                 return 0;
    102 
    103         return waitTime;
     71void VideoDecoder::reset() {
     72        _curFrame = -1;
     73        _startTime = 0;
    10474}
    10575
    106 void VideoDecoder::copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch) {
    107         uint h = getHeight();
    108         uint w = getWidth();
    109 
    110         byte *src = _videoFrameBuffer;
    111         dst += y * pitch + x;
    112 
    113         do {
    114                 memcpy(dst, src, w);
    115                 dst += pitch;
    116                 src += w;
    117         } while (--h);
     76bool VideoDecoder::endOfVideo() const {
     77        return !isVideoLoaded() || getCurFrame() >= (int32)getFrameCount() - 1;
    11878}
    11979
    120 void VideoDecoder::setPalette(byte *pal) {
    121         byte videoPalette[256 * 4];
     80uint32 FixedRateVideoDecoder::getTimeToNextFrame() const {
     81        if (endOfVideo() || _curFrame < 0)
     82                return 0;
    12283
    123         uint32 maxWeight = 0;
    124         uint32 minWeight = 0xFFFFFFFF;
    125         uint32 weight = 0;
    126         byte r, g, b;
     84        uint32 elapsedTime = getElapsedTime();
     85        uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1);
    12786
    128         for (int i = 0; i < 256; i++) {
    129                 videoPalette[i * 4 + 0] = *pal++;
    130                 videoPalette[i * 4 + 1] = *pal++;
    131                 videoPalette[i * 4 + 2] = *pal++;
    132                 videoPalette[i * 4 + 3] = 0;
     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;
    13391
    134                 // Try and find the white and black colors for the current palette
    135                 r = videoPalette[i * 4 + 0];
    136                 g = videoPalette[i * 4 + 1];
    137                 b = videoPalette[i * 4 + 2];
    138 
    139                 weight = 3 * r * r + 6 * g * g + 2 * b * b;
    140 
    141                 if (weight >= maxWeight) {
    142                         _curFrameWhite = i;
    143                         maxWeight = weight;
    144                 }
    145 
    146                 if (weight <= minWeight) {
    147                         _curFrameBlack = i;
    148                         minWeight = i;
    149                 }
    150         }
    151 
    152         g_system->setPalette(videoPalette, 0, 256);
     92        return nextFrameStartTime - elapsedTime;
    15393}
    15494
    155 
    156 /*
    157  *  VideoPlayer
    158  */
    159 
    160 void VideoPlayer::processVideoEvents(Common::List<Common::Event> &stopEvents) {
    161         Common::Event curEvent;
    162         Common::EventManager *eventMan = g_system->getEventManager();
    163 
    164         // Process events, and skip video if esc is pressed
    165         while (eventMan->pollEvent(curEvent)) {
    166                 if (curEvent.type == Common::EVENT_RTL || curEvent.type == Common::EVENT_QUIT) {
    167                         _skipVideo = true;
    168                 }
    169 
    170                 for (Common::List<Common::Event>::const_iterator iter = stopEvents.begin(); iter != stopEvents.end(); ++iter) {
    171                         if (curEvent.type == iter->type) {
    172                                 if (iter->type == Common::EVENT_KEYDOWN || iter->type == Common::EVENT_KEYUP) {
    173                                         if (curEvent.kbd.keycode == iter->kbd.keycode) {
    174                                                 _skipVideo = true;
    175                                                 break;
    176                                         }
    177                                 } else {
    178                                         _skipVideo = true;
    179                                         break;
    180                                 }
    181                         }
    182                 }
    183         }
     95uint32 FixedRateVideoDecoder::getFrameBeginTime(uint32 frame) const {
     96        return (uint32)(frame * 1000 / getFrameRate());
    18497}
    18598
    186 bool VideoPlayer::playVideo(Common::List<Common::Event> &stopEvents) {
    187         _skipVideo = false;
    188         debug(0, "Playing video");
    189 
    190         g_system->fillScreen(0);
    191 
    192         int frameX = (g_system->getWidth() - _decoder->getWidth()) / 2;
    193         int frameY = (g_system->getHeight() - _decoder->getHeight()) / 2;
    194 
    195         while (_decoder->getCurFrame() < _decoder->getFrameCount() && !_skipVideo) {
    196                 processVideoEvents(stopEvents);
    197 
    198                 uint32 startTime = 0;
    199                 _decoder->decodeNextFrame();
    200 
    201                 Graphics::Surface *screen = g_system->lockScreen();
    202                 _decoder->copyFrameToBuffer((byte *)screen->pixels, frameX, frameY, g_system->getWidth());
    203                 performPostProcessing((byte *)screen->pixels);
    204                 g_system->unlockScreen();
    205 
    206                 uint32 waitTime = _decoder->getFrameWaitTime();
    207 
    208                 if (!waitTime) {
    209                         warning("dropped frame %i", _decoder->getCurFrame());
    210                         continue;
    211                 }
    212 
    213                 // Update the screen
    214                 g_system->updateScreen();
    215 
    216                 startTime = g_system->getMillis();
    217 
    218                 // Wait before showing the next frame
    219                 while (g_system->getMillis() < startTime + waitTime && !_skipVideo) {
    220                         processVideoEvents(stopEvents);
    221                         g_system->delayMillis(10);
    222                 }
    223         }
    224 
    225         return !_skipVideo;
    226 }
    227 
    228 bool VideoPlayer::playVideo() {
    229         Common::Event stopEvent;
    230         Common::List<Common::Event> stopEvents;
    231         stopEvents.clear();
    232         stopEvent.type = Common::EVENT_KEYDOWN;
    233         stopEvent.kbd = Common::KEYCODE_ESCAPE;
    234         stopEvents.push_back(stopEvent);
    235 
    236         return playVideo(stopEvents);
    237 }
    238 
    239 void VideoPlayer::performPostProcessing(byte *screen) {
    240 }
    241 
    24299} // End of namespace Graphics