Ticket #9141: video_decoder_rewrite.diff
File video_decoder_rewrite.diff, 132.0 KB (added by , 14 years ago) |
---|
-
engines/mohawk/video/cinepak.h
65 65 ~CinepakDecoder(); 66 66 67 67 Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); 68 Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } 68 69 69 70 private: 70 71 CinepakFrame _curFrame; -
engines/mohawk/video/rpza.h
37 37 ~RPZADecoder() { delete _surface; } 38 38 39 39 Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); 40 Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } 40 41 41 42 private: 42 43 Graphics::Surface *_surface; -
engines/mohawk/video/smc.h
43 43 ~SMCDecoder() { delete _surface; } 44 44 45 45 Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); 46 Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } 46 47 47 48 private: 48 49 Graphics::Surface *_surface; -
engines/mohawk/video/qtrle.h
37 37 ~QTRLEDecoder(); 38 38 39 39 Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); 40 Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } 40 41 41 42 private: 42 43 byte _bitsPerPixel; -
engines/mohawk/jpeg.h
45 45 ~JPEGDecoder(); 46 46 47 47 Graphics::Surface *decodeImage(Common::SeekableReadStream *stream); 48 Graphics::PixelFormat getPixelFormat() const { return _pixelFormat; } 48 49 49 50 private: 50 51 Graphics::PixelFormat _pixelFormat; -
engines/tucker/sequences.cpp
760 760 } 761 761 762 762 bool AnimationSequencePlayer::decodeNextAnimationFrame(int index) { 763 bool framesLeft = _flicPlayer[index].decodeNextFrame(); 763 ::Graphics::Surface *surface = _flicPlayer[index].decodeNextFrame(); 764 764 765 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); 766 768 } else { 767 769 _flicPlayer[index].copyDirtyRectsToBuffer(_offscreenBuffer, kScreenWidth); 768 770 ++_frameCounter; 769 771 } 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(); 776 777 } 777 778 778 779 void AnimationSequencePlayer::loadIntroSeq17_18() { … … 797 798 // The intro credits animation. This uses 2 animations: the foreground one, which 798 799 // is the actual intro credits, and the background one, which is an animation of 799 800 // 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()) 802 806 _flicPlayer[1].reset(); 803 }804 807 } 808 805 809 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) 812 817 _changeToNextSequence = true; 813 }814 818 } 815 819 816 820 void AnimationSequencePlayer::displayLoadingScreen() { … … 864 868 void AnimationSequencePlayer::playIntroSeq3_4() { 865 869 if (!_updateScreenPicture) { 866 870 bool framesLeft = decodeNextAnimationFrame(0); 867 if (_flicPlayer[0].getCurFrame() == 70 6) {871 if (_flicPlayer[0].getCurFrame() == 707) { 868 872 initPicPart4(); 869 873 } 870 874 if (!framesLeft) { … … 903 907 } 904 908 905 909 void 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 906 917 int offset = 0; 907 918 for (int y = 0; y < kScreenHeight; ++y) { 908 919 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) 911 923 color = _picBufPtr[800 + y * 640 + _updateScreenWidth + x]; 912 } 924 913 925 _offscreenBuffer[offset++] = color; 914 926 } 915 927 } … … 924 936 } 925 937 926 938 void 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) { 929 940 drawPic1Part10(); 930 941 _updateScreenWidth += 6; 931 } else if (_flicPlayer[0].getCurFrame() == 984) { 942 } else if (_flicPlayer[0].getCurFrame() == 985) { 943 decodeNextAnimationFrame(0); 932 944 drawPic2Part10(); 933 } else if (_flicPlayer[0].getCurFrame() >= 98 8 && _flicPlayer[0].getCurFrame() <= 996) {945 } else if (_flicPlayer[0].getCurFrame() >= 989 && _flicPlayer[0].getCurFrame() <= 997) { 934 946 drawPic1Part10(); 935 947 _updateScreenWidth -= 25; 936 948 if (_updateScreenWidth < 0) { 937 949 _updateScreenWidth = 0; 938 950 } 939 951 } 940 if (!framesLeft) { 952 953 if (_flicPlayer[0].endOfVideo()) 941 954 _changeToNextSequence = true; 942 }943 955 } 944 956 945 957 void AnimationSequencePlayer::loadIntroSeq21_22() { -
engines/saga/scene.h
424 424 int DinoStartProc(); 425 425 int FTA2StartProc(); 426 426 int FTA2EndProc(FTA2Endings whichEnding); 427 void playMovie(const char *filename); 427 428 428 429 void IHNMLoadCutaways(); 429 430 bool checkKey(); -
engines/saga/introproc_saga2.cpp
40 40 int Scene::DinoStartProc() { 41 41 _vm->_gfx->showCursor(false); 42 42 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"); 50 44 51 45 // HACK: Forcibly quit here 52 46 _vm->quitGame(); … … 57 51 int Scene::FTA2StartProc() { 58 52 _vm->_gfx->showCursor(false); 59 53 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"); 70 56 71 57 // HACK: Forcibly quit here 72 58 _vm->quitGame(); … … 100 86 _vm->_gfx->showCursor(false); 101 87 102 88 // 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); 111 90 112 91 return SUCCESS; 113 92 } 114 93 94 void 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 115 124 } // End of namespace Saga 116 125 117 126 #endif -
engines/sci/console.cpp
223 223 if (!_videoFile.empty()) { 224 224 _engine->_gfxCursor->kernelHide(); 225 225 226 Graphics::VideoDecoder *videoDecoder = 0; 227 226 228 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 246 232 } 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()); 257 234 #endif 235 } else if (_videoFile.hasSuffix(".avi")) { 236 videoDecoder = new Graphics::AviDecoder(g_system->getMixer()); 258 237 } 259 238 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 260 267 _engine->_gfxCursor->kernelShow(); 261 262 268 _videoFile.clear(); 263 269 _videoFrameDelay = 0; 264 270 } -
engines/sci/engine/kgraphics.cpp
1076 1076 } 1077 1077 1078 1078 reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { 1079 bool playedVideo = false;1080 1081 1079 // Hide the cursor if it's showing and then show it again if it was 1082 1080 // previously visible. 1083 1081 bool reshowCursor; … … 1085 1083 reshowCursor = g_sci->_gfxCursor->isVisible(); 1086 1084 if (reshowCursor) 1087 1085 g_sci->_gfxCursor->kernelHide(); 1086 1087 Graphics::VideoDecoder *videoDecoder = 0; 1088 1088 1089 1089 if (argv[0].segment != 0) { 1090 1090 // DOS SEQ 1091 1091 // SEQ's are called with no subops, just the string and delay 1092 1092 Common::String filename = s->_segMan->getString(argv[0]); 1093 int delay = argv[1].toUint16(); // Time between frames in ticks1094 1093 1095 1094 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)) { 1101 1099 warning("Failed to open movie file %s", filename.c_str()); 1100 delete videoDecoder; 1101 videoDecoder = 0; 1102 1102 } 1103 seqDecoder->closeFile();1104 delete player;1105 delete seqDecoder;1106 1103 } else { 1107 1104 // Windows AVI (Macintosh QuickTime? Need to check KQ6 Macintosh) 1108 1105 // TODO: This appears to be some sort of subop. case 0 contains the string … … 1121 1118 switch (argv[0].toUint16()) { 1122 1119 case 0: { 1123 1120 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())) { 1130 1124 warning("Failed to open movie file %s", filename.c_str()); 1125 delete videoDecoder; 1126 videoDecoder = 0; 1131 1127 } 1132 aviDecoder->closeFile();1133 delete player;1134 delete aviDecoder;1135 1128 break; 1136 1129 } 1137 1130 default: … … 1139 1132 } 1140 1133 } 1141 1134 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; 1143 1160 g_sci->_gfxScreen->kernelSyncWithFramebuffer(); 1161 } 1144 1162 1145 1163 if (reshowCursor) 1146 1164 g_sci->_gfxCursor->kernelShow(); -
engines/sci/video/vmd_decoder.h
29 29 #define GRAPHICS_VIDEO_VMD_DECODER_H 30 30 31 31 #include "graphics/video/coktelvideo/coktelvideo.h" 32 #include "graphics/video/video_ player.h"32 #include "graphics/video/video_decoder.h" 33 33 #include "sound/mixer.h" 34 34 35 35 namespace Sci { … … 49 49 * - Shivers 2: Harvest of Souls 50 50 * - Torin's Passage 51 51 */ 52 class VMDDecoder : public Graphics:: VideoDecoder {52 class VMDDecoder : public Graphics::FixedRateVideoDecoder { 53 53 public: 54 54 VMDDecoder(Audio::Mixer *mixer); 55 55 virtual ~VMDDecoder(); 56 56 57 57 uint32 getFrameWaitTime(); 58 58 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(); 64 61 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; } 69 70 70 bool decodeNextFrame(); 71 protected: 72 double getFrameRate() const { return _vmdDecoder->getFrameRate(); } 71 73 72 74 private: 73 75 Graphics::Vmd *_vmdDecoder; 74 76 Audio::Mixer *_mixer; 77 Graphics::Surface *_surface; 78 Common::SeekableReadStream *_fileStream; 75 79 byte _palette[256 * 3]; 80 bool _dirtyPalette; 76 81 77 void getPalette();82 void loadPaletteFromVMD(); 78 83 }; 79 84 80 85 } // End of namespace Graphics -
engines/sci/video/seq_decoder.h
26 26 #ifndef SEQ_DECODER_H 27 27 #define SEQ_DECODER_H 28 28 29 #include "graphics/video/video_ player.h"29 #include "graphics/video/video_decoder.h" 30 30 31 31 namespace Sci { 32 32 33 33 /** 34 34 * Implementation of the Sierra SEQ decoder, used in KQ6 DOS floppy/CD and GK1 DOS 35 35 */ 36 class SeqDecoder : public Graphics:: VideoDecoder {36 class SeqDecoder : public Graphics::FixedRateVideoDecoder { 37 37 public: 38 SeqDecoder() {}38 SeqDecoder(); 39 39 virtual ~SeqDecoder(); 40 40 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; } 46 45 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; } 53 54 54 /** 55 * Close a SEQ encoded video file 56 */ 57 void closeFile(); 55 protected: 56 double getFrameRate() const { assert(_frameDelay); return 60.0 / _frameDelay; } 58 57 59 bool decodeNextFrame();60 61 58 private: 62 59 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; 63 67 }; 64 68 65 69 } // End of namespace Sci -
engines/sci/video/vmd_decoder.cpp
27 27 28 28 #include "sci/video/vmd_decoder.h" 29 29 30 #include "common/archive.h"31 30 #include "common/endian.h" 32 31 #include "common/util.h" 33 32 #include "common/stream.h" … … 42 41 43 42 VMDDecoder::VMDDecoder(Audio::Mixer *mixer) : _mixer(mixer) { 44 43 _vmdDecoder = new Graphics::Vmd(new Graphics::PaletteLUT(5, Graphics::PaletteLUT::kPaletteYUV)); 44 _surface = 0; 45 _dirtyPalette = false; 46 _fileStream = 0; 45 47 } 46 48 47 49 VMDDecoder::~VMDDecoder() { 48 close File();50 close(); 49 51 } 50 52 51 uint32 VMDDecoder::getFrameWaitTime() { 52 return _vmdDecoder->getFrameWaitTime(); 53 } 53 bool VMDDecoder::load(Common::SeekableReadStream &stream) { 54 close(); 54 55 55 bool VMDDecoder::loadFile(const char *fileName) { 56 closeFile(); 57 58 _fileStream = SearchMan.createReadStreamForMember(fileName); 59 if (!_fileStream) 56 if (!_vmdDecoder->load(stream)) 60 57 return false; 61 58 62 if (!_vmdDecoder->load(*_fileStream)) 63 return false; 59 _fileStream = &stream; 64 60 65 if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette) { 66 getPalette(); 67 setPalette(_palette); 68 } 61 if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette) 62 loadPaletteFromVMD(); 69 63 70 64 if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesSound) 71 65 _vmdDecoder->enableSound(*_mixer); 72 66 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 VMDs80 81 67 if (_vmdDecoder->hasExtraData()) 82 68 warning("This VMD video has extra embedded data, which is currently not handled"); 83 69 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); 89 73 return true; 90 74 } 91 75 92 void VMDDecoder::close File() {76 void VMDDecoder::close() { 93 77 if (!_fileStream) 94 78 return; 95 79 … … 98 82 delete _fileStream; 99 83 _fileStream = 0; 100 84 101 delete[] _videoFrameBuffer; 102 _videoFrameBuffer = 0; 85 _surface->free(); 86 delete _surface; 87 _surface = 0; 88 89 reset(); 103 90 } 104 91 105 bool VMDDecoder::decodeNextFrame() { 106 if (_videoInfo.currentFrame == 0) 107 _videoInfo.startTime = g_system->getMillis(); 108 92 Graphics::Surface *VMDDecoder::decodeNextFrame() { 109 93 Graphics::CoktelVideo::State state = _vmdDecoder->nextFrame(); 110 94 111 if (state.flags & Graphics::CoktelVideo::kStatePalette) { 112 getPalette(); 113 setPalette(_palette); 114 } 95 if (state.flags & Graphics::CoktelVideo::kStatePalette) 96 loadPaletteFromVMD(); 115 97 116 return ++_videoInfo.currentFrame < _videoInfo.frameCount; 98 if (_curFrame == -1) 99 _startTime = g_system->getMillis(); 100 101 _curFrame++; 102 return _surface; 117 103 } 118 104 119 void VMDDecoder:: getPalette() {105 void VMDDecoder::loadPaletteFromVMD() { 120 106 const byte *pal = _vmdDecoder->getPalette(); 121 107 122 108 for (int i = 0; i < 256; i++) { … … 124 110 _palette[i * 3 + 1] = pal[i * 3 + 1] << 2; 125 111 _palette[i * 3 + 2] = pal[i * 3 + 2] << 2; 126 112 } 113 114 _dirtyPalette = true; 127 115 } 128 116 129 117 } // End of namespace Graphics -
engines/sci/video/seq_decoder.cpp
35 35 36 36 namespace Sci { 37 37 38 // SEQ videos always run at 320x20039 #define SCREEN_WIDTH 32040 #define SCREEN_HEIGHT 20041 42 38 enum seqPalTypes { 43 39 kSeqPalVariable = 0, 44 40 kSeqPalConstant = 1 … … 49 45 kSeqFrameDiff = 1 50 46 }; 51 47 48 SeqDecoder::SeqDecoder() { 49 _fileStream = 0; 50 _surface = 0; 51 _dirtyPalette = false; 52 } 53 52 54 SeqDecoder::~SeqDecoder() { 53 close File();55 close(); 54 56 } 55 57 56 bool SeqDecoder::load File(const char *fileName, int frameDelay) {57 close File();58 bool SeqDecoder::load(Common::SeekableReadStream &stream) { 59 close(); 58 60 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); 62 64 63 // Seek to the first frame 64 _videoInfo.currentFrame = 0; 65 _frameCount = _fileStream->readUint16LE(); 65 66 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 here70 _videoInfo.frameDelay = 100 * frameDelay * 1000 / 60;71 _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height];72 73 67 // Set palette 74 68 int paletteSize = _fileStream->readUint32LE(); 75 69 … … 81 75 uint16 palColorStart = READ_LE_UINT16(paletteData + 25); 82 76 uint16 palColorCount = READ_LE_UINT16(paletteData + 29); 83 77 84 byte palette[256 * 4];85 78 int palOffset = 37; 86 79 87 80 for (uint16 colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { 88 81 if (palFormat == kSeqPalVariable) 89 82 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++]; 94 86 } 95 87 96 g_system->setPalette(palette, 0, 256); 97 88 _dirtyPalette = true; 98 89 delete[] paletteData; 99 100 _videoInfo.firstframeOffset = _fileStream->pos();101 102 90 return true; 103 91 } 104 92 105 void SeqDecoder::close File() {93 void SeqDecoder::close() { 106 94 if (!_fileStream) 107 95 return; 108 96 97 _frameDelay = 0; 98 109 99 delete _fileStream; 110 100 _fileStream = 0; 111 101 112 delete[] _videoFrameBuffer; 113 _videoFrameBuffer = 0; 102 _surface->free(); 103 delete _surface; 104 _surface = 0; 105 106 reset(); 114 107 } 115 108 116 boolSeqDecoder::decodeNextFrame() {109 Graphics::Surface *SeqDecoder::decodeNextFrame() { 117 110 int16 frameWidth = _fileStream->readUint16LE(); 118 111 int16 frameHeight = _fileStream->readUint16LE(); 119 112 int16 frameLeft = _fileStream->readUint16LE(); … … 129 122 130 123 _fileStream->seek(offset); 131 124 132 if (_videoInfo.currentFrame == 0)133 _videoInfo.startTime = g_system->getMillis();134 135 125 if (frameType == kSeqFrameFull) { 136 byte *dst = _videoFrameBuffer + frameTop * SCREEN_WIDTH+ frameLeft;126 byte *dst = (byte *)_surface->pixels + frameTop * getWidth() + frameLeft; 137 127 138 128 byte *linebuf = new byte[frameWidth]; 139 129 140 130 do { 141 131 _fileStream->read(linebuf, frameWidth); 142 132 memcpy(dst, linebuf, frameWidth); 143 dst += SCREEN_WIDTH;133 dst += getWidth(); 144 134 } while (--frameHeight); 145 135 146 136 delete[] linebuf; 147 137 } else { 148 138 byte *buf = new byte[frameSize]; 149 139 _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); 151 141 delete[] buf; 152 142 } 153 143 154 return ++_videoInfo.currentFrame < _videoInfo.frameCount; 144 if (_curFrame == -1) 145 _startTime = g_system->getMillis(); 146 147 _curFrame++; 148 return _surface; 155 149 } 156 150 157 151 #define WRITE_TO_BUFFER(n) \ 158 if (writeRow * SCREEN_WIDTH + writeCol + (n) > SCREEN_WIDTH* height) { \152 if (writeRow * getWidth() + writeCol + (n) > getWidth() * height) { \ 159 153 warning("SEQ player: writing out of bounds, aborting"); \ 160 154 return false; \ 161 155 } \ 162 156 if (litPos + (n) > litSize) { \ 163 157 warning("SEQ player: reading out of bounds, aborting"); \ 164 158 } \ 165 memcpy(dest + writeRow * SCREEN_WIDTH+ writeCol, litData + litPos, n);159 memcpy(dest + writeRow * getWidth() + writeCol, litData + litPos, n); 166 160 167 161 bool SeqDecoder::decodeFrame(byte *rleData, int rleSize, byte *litData, int litSize, byte *dest, int left, int width, int height, int colorKey) { 168 162 int writeRow = 0; -
engines/sword1/animation.h
28 28 29 29 #include "graphics/video/dxa_decoder.h" 30 30 #include "graphics/video/smk_decoder.h" 31 #include "graphics/video/video_ player.h"31 #include "graphics/video/video_decoder.h" 32 32 33 33 #include "sword1/screen.h" 34 34 #include "sword1/sound.h" … … 61 61 DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle); 62 62 ~DXADecoderWithSound() {} 63 63 64 int32 getAudioLag(); 64 uint32 getElapsedTime() const; 65 65 66 private: 66 67 Audio::Mixer *_mixer; 67 68 Audio::SoundHandle *_bgSoundHandle; 68 69 }; 69 70 70 class MoviePlayer : public Graphics::VideoPlayer{71 class MoviePlayer { 71 72 public: 72 73 MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType); 73 74 virtual ~MoviePlayer(); 74 75 bool load(uint32 id); 75 76 void play(); 77 76 78 protected: 77 79 SwordEngine *_vm; 78 80 Text *_textMan; … … 82 84 int _textX, _textY, _textWidth, _textHeight; 83 85 DecoderType _decoderType; 84 86 87 Graphics::VideoDecoder *_decoder; 85 88 Audio::SoundHandle *_bgSoundHandle; 86 89 Audio::AudioStream *_bgSoundStream; 87 90 91 bool playVideo(); 88 92 void performPostProcessing(byte *screen); 93 94 byte findBlackPalIndex(); 95 byte findWhitePalIndex(); 89 96 }; 90 97 91 98 MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system); -
engines/sword1/animation.cpp
68 68 /////////////////////////////////////////////////////////////////////////////// 69 69 70 70 MoviePlayer::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) { 72 72 _bgSoundStream = NULL; 73 73 _decoderType = decoderType; 74 _decoder = decoder; 74 75 } 75 76 76 77 MoviePlayer::~MoviePlayer() { … … 86 87 Common::File f; 87 88 char filename[20]; 88 89 89 if (_decoderType == kVideoDecoderDXA) {90 if (_decoderType == kVideoDecoderDXA) 90 91 _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(sequenceList[id]); 91 } else {92 else 92 93 _bgSoundStream = NULL; 93 }94 94 95 95 if (SwordEngine::_systemVars.showText) { 96 96 sprintf(filename, "%s.txt", sequenceList[id]); … … 146 146 } 147 147 148 148 void MoviePlayer::play() { 149 if (_bgSoundStream) {149 if (_bgSoundStream) 150 150 _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream); 151 } 151 152 152 bool terminated = false; 153 153 154 154 _textX = 0; … … 205 205 for (x = 0; x < _textWidth; x++) { 206 206 switch (src[x]) { 207 207 case BORDER_COL: 208 dst[x] = _decoder->getBlack();208 dst[x] = findBlackPalIndex(); 209 209 break; 210 210 case LETTER_COL: 211 dst[x] = _decoder->getWhite();211 dst[x] = findWhitePalIndex(); 212 212 break; 213 213 } 214 214 } … … 228 228 229 229 for (y = 0; y < _textHeight; y++) { 230 230 if (_textY + y < frameY || _textY + y >= frameY + frameHeight) { 231 memset(dst + _textX, _decoder->getBlack(), _textWidth);231 memset(dst + _textX, findBlackPalIndex(), _textWidth); 232 232 } else { 233 233 if (frameX > _textX) 234 memset(dst + _textX, _decoder->getBlack(), frameX - _textX);234 memset(dst + _textX, findBlackPalIndex(), frameX - _textX); 235 235 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)); 237 237 } 238 238 239 239 dst += _system->getWidth(); … … 244 244 } 245 245 } 246 246 247 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) 248 : _mixer(mixer), _bgSoundHandle(bgSoundHandle) { 247 bool 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; 249 273 } 250 274 251 int32 DXADecoderWithSound::getAudioLag() {252 if (!_fileStream)253 return 0; 275 byte MoviePlayer::findBlackPalIndex() { 276 return 0; 277 } 254 278 255 if (!_mixer->isSoundHandleActive(*_bgSoundHandle)) 256 return 0; 279 byte MoviePlayer::findWhitePalIndex() { 280 return 0xff; 281 } 257 282 258 int32 frameDelay = getFrameDelay(); 259 int32 videoTime = _videoInfo.currentFrame * frameDelay;260 int32 audioTime; 283 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) 284 : _mixer(mixer), _bgSoundHandle(bgSoundHandle) { 285 } 261 286 262 const Audio::Timestamp ts = _mixer->getElapsedTime(*_bgSoundHandle); 263 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames(); 287 uint32 DXADecoderWithSound::getElapsedTime() const { 288 if (_mixer->isSoundHandleActive(*_bgSoundHandle)) 289 return _mixer->getSoundElapsedTime(*_bgSoundHandle); 264 290 265 return videoTime - audioTime;291 return VideoDecoder::getElapsedTime(); 266 292 } 267 293 268 294 /////////////////////////////////////////////////////////////////////////////// -
engines/sword2/animation.h
30 30 31 31 #include "graphics/video/dxa_decoder.h" 32 32 #include "graphics/video/smk_decoder.h" 33 #include "graphics/video/video_ player.h"33 #include "graphics/video/video_decoder.h" 34 34 #include "sound/mixer.h" 35 35 36 36 #include "sword2/screen.h" … … 63 63 DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle); 64 64 ~DXADecoderWithSound() {} 65 65 66 int32 getAudioLag();66 uint32 getElapsedTime() const; 67 67 private: 68 68 Audio::Mixer *_mixer; 69 69 Audio::SoundHandle *_bgSoundHandle; 70 70 }; 71 71 72 class MoviePlayer : public Graphics::VideoPlayer{72 class MoviePlayer { 73 73 public: 74 74 MoviePlayer(Sword2Engine *vm, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Graphics::VideoDecoder *decoder, DecoderType decoderType); 75 75 virtual ~MoviePlayer(); … … 89 89 int _textX, _textY; 90 90 DecoderType _decoderType; 91 91 92 Graphics::VideoDecoder *_decoder; 92 93 Audio::SoundHandle *_bgSoundHandle; 93 94 Audio::AudioStream *_bgSoundStream; 94 95 … … 96 97 int _leadOutFrame; 97 98 98 99 void performPostProcessing(byte *screen); 100 bool playVideo(); 99 101 100 102 void openTextObject(uint32 index); 101 103 void closeTextObject(uint32 index, byte *screen); 102 104 void drawTextObject(uint32 index, byte *screen); 105 106 byte findBlackPalIndex(); 107 byte findWhitePalIndex(); 103 108 }; 104 109 105 110 MoviePlayer *makeMoviePlayer(const char *name, Sword2Engine *vm, Audio::Mixer *snd, OSystem *system); -
engines/sword2/animation.cpp
47 47 /////////////////////////////////////////////////////////////////////////////// 48 48 49 49 MoviePlayer::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) { 51 51 _bgSoundStream = NULL; 52 52 _decoderType = decoderType; 53 _decoder = decoder; 53 54 } 54 55 55 56 MoviePlayer:: ~MoviePlayer() { … … 62 63 * @param id the id of the file 63 64 */ 64 65 bool MoviePlayer::load(const char *name) { 65 if (_decoderType == kVideoDecoderDXA) {66 if (_decoderType == kVideoDecoderDXA) 66 67 _bgSoundStream = Audio::SeekableAudioStream::openStreamFile(name); 67 } else {68 else 68 69 _bgSoundStream = NULL; 69 }70 70 71 71 _textSurface = NULL; 72 72 … … 97 97 _currentMovieText = 0; 98 98 _leadOut = leadOut; 99 99 100 if (leadIn) {100 if (leadIn) 101 101 _vm->_sound->playMovieSound(leadIn, kLeadInSound); 102 }103 102 104 if (_bgSoundStream) {103 if (_bgSoundStream) 105 104 _snd->playInputStream(Audio::Mixer::kSFXSoundType, _bgSoundHandle, _bgSoundStream); 106 }107 105 108 106 bool terminated = false; 109 107 … … 186 184 187 185 for (int y = 0; y < text->_textSprite.h; y++) { 188 186 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); 190 188 } else { 191 189 if (frameX > _textX) 192 memset(dst + _textX, _decoder->getBlack(), frameX - _textX);190 memset(dst + _textX, findBlackPalIndex(), frameX - _textX); 193 191 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)); 195 193 } 196 194 197 195 dst += _system->getWidth(); … … 207 205 void MoviePlayer::drawTextObject(uint32 index, byte *screen) { 208 206 MovieText *text = &_movieTexts[index]; 209 207 210 byte white = _decoder->getWhite();211 byte black = _decoder->getBlack();208 byte white = findWhitePalIndex(); 209 byte black = findBlackPalIndex(); 212 210 213 211 if (text->_textMem && _textSurface) { 214 212 byte *src = text->_textSprite.data; … … 272 270 } 273 271 } 274 272 275 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) 276 : _mixer(mixer), _bgSoundHandle(bgSoundHandle) { 273 bool 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; 277 299 } 278 300 279 int32 DXADecoderWithSound::getAudioLag() {280 if (!_fileStream)281 return 0; 301 byte MoviePlayer::findBlackPalIndex() { 302 return 0; 303 } 282 304 283 if (!_mixer->isSoundHandleActive(*_bgSoundHandle)) 284 return 0; 305 byte MoviePlayer::findWhitePalIndex() { 306 return 0xff; 307 } 285 308 286 int32 frameDelay = getFrameDelay(); 287 int32 videoTime = _videoInfo.currentFrame * frameDelay;288 int32 audioTime; 309 DXADecoderWithSound::DXADecoderWithSound(Audio::Mixer *mixer, Audio::SoundHandle *bgSoundHandle) 310 : _mixer(mixer), _bgSoundHandle(bgSoundHandle) { 311 } 289 312 290 const Audio::Timestamp ts = _mixer->getElapsedTime(*_bgSoundHandle); 291 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames(); 313 uint32 DXADecoderWithSound::getElapsedTime() const { 314 if (_mixer->isSoundHandleActive(*_bgSoundHandle)) 315 return _mixer->getSoundElapsedTime(*_bgSoundHandle); 292 316 293 return videoTime - audioTime;317 return VideoDecoder::getElapsedTime(); 294 318 } 295 319 296 320 /////////////////////////////////////////////////////////////////////////////// -
engines/scumm/he/animation_he.h
56 56 57 57 void copyFrameToBuffer(byte *dst, int dstType, uint x, uint y, uint pitch); 58 58 void handleNextFrame(); 59 60 protected:61 virtual void setPalette(byte *pal);62 59 }; 63 60 64 61 } // End of namespace Scumm -
engines/scumm/he/script_v90he.cpp
1437 1437 } 1438 1438 } else if (_videoParams.status == 165) { 1439 1439 // Stop video 1440 _moviePlay->close File();1440 _moviePlay->close(); 1441 1441 } 1442 1442 break; 1443 1443 default: … … 1464 1464 break; 1465 1465 case 52: // Get current frame 1466 1466 pop(); 1467 push(_moviePlay-> getCurFrame());1467 push(_moviePlay->endOfVideo() ? -1 : (_moviePlay->getCurFrame() + 1)); 1468 1468 break; 1469 1469 case 63: // Get image number 1470 1470 pop(); -
engines/scumm/he/script_v100he.cpp
2254 2254 } 2255 2255 } else if (_videoParams.status == 19) { 2256 2256 // Stop video 2257 _moviePlay->close File();2257 _moviePlay->close(); 2258 2258 } 2259 2259 break; 2260 2260 default: … … 2937 2937 break; 2938 2938 case 73: 2939 2939 pop(); 2940 push(_moviePlay-> getCurFrame());2940 push(_moviePlay->endOfVideo() ? -1 : (_moviePlay->getCurFrame() + 1)); 2941 2941 break; 2942 2942 case 84: 2943 2943 pop(); -
engines/scumm/he/animation_he.cpp
46 46 } 47 47 48 48 int MoviePlayer::load(const char *filename, int flags, int image) { 49 if (isVideoLoaded()) { 50 closeFile(); 51 } 49 if (isVideoLoaded()) 50 close(); 52 51 53 if (!loadFile( filename)) {52 if (!loadFile(Common::String(filename))) { 54 53 warning("Failed to load video file %s", filename); 55 54 return -1; 56 55 } 56 57 57 debug(1, "Playing video %s", filename); 58 58 59 if (flags & 2) {59 if (flags & 2) 60 60 _vm->_wiz->createWizEmptyImage(image, 0, 0, getWidth(), getHeight()); 61 }62 61 63 62 _flags = flags; 64 63 _wizResNum = image; 65 66 64 return 0; 67 65 } 68 66 … … 70 68 uint h = getHeight(); 71 69 uint w = getWidth(); 72 70 73 byte *src = _videoFrameBuffer; 71 Graphics::Surface *surface = decodeNextFrame(); 72 byte *src = (byte *)surface->pixels; 74 73 74 if (hasDirtyPalette()) 75 _vm->setPaletteFromPtr(getPalette(), 256); 76 75 77 if (_vm->_game.features & GF_16BIT_COLOR) { 76 78 dst += y * pitch + x * 2; 77 79 do { … … 102 104 } 103 105 104 106 void MoviePlayer::handleNextFrame() { 105 if (!isVideoLoaded()) {107 if (!isVideoLoaded()) 106 108 return; 107 }108 109 109 110 VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen]; 110 111 111 decodeNextFrame();112 113 112 if (_flags & 2) { 114 113 uint8 *dstPtr = _vm->getResourceAddress(rtImage, _wizResNum); 115 114 assert(dstPtr); … … 128 127 _vm->markRectAsDirty(kMainVirtScreen, imageRect); 129 128 } 130 129 131 if (getCurFrame() == getFrameCount()) { 132 closeFile(); 133 } 130 if (endOfVideo()) 131 close(); 134 132 } 135 133 136 void MoviePlayer::setPalette(byte *pal) {137 _vm->setPaletteFromPtr(pal, 256);138 }139 140 134 } // End of namespace Scumm 141 135 142 136 #endif // ENABLE_HE -
engines/agos/animation.h
72 72 virtual void handleNextFrame(); 73 73 virtual bool processFrame() = 0; 74 74 virtual void startSound() {}; 75 76 protected: 77 uint32 _firstFrameOffset; 75 78 }; 76 79 77 80 class MoviePlayerDXA : public MoviePlayer, ::Graphics::DXADecoder { … … 84 87 void playVideo(); 85 88 void nextFrame(); 86 89 virtual void stopVideo(); 87 protected:88 void setPalette(byte *pal);89 90 90 91 private: 91 92 void handleNextFrame(); 92 93 bool processFrame(); 93 94 void startSound(); 95 void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch); 94 96 }; 95 97 96 98 class MoviePlayerSMK : public MoviePlayer, ::Graphics::SmackerDecoder { … … 101 103 void playVideo(); 102 104 void nextFrame(); 103 105 virtual void stopVideo(); 104 protected: 105 void setPalette(byte *pal); 106 106 107 private: 107 108 void handleNextFrame(); 108 109 bool processFrame(); 109 110 void startSound(); 111 void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch); 110 112 }; 111 113 112 114 MoviePlayer *makeMoviePlayer(AGOSEngine_Feeble *vm, const char *name); -
engines/agos/animation.cpp
241 241 } 242 242 243 243 bool MoviePlayerDXA::load() { 244 char videoName[20];245 uint i;246 247 244 if ((_vm->getPlatform() == Common::kPlatformAmiga || _vm->getPlatform() == Common::kPlatformMacintosh) && 248 245 _vm->_language != Common::EN_ANY) { 249 246 _sequenceNum = 0; 250 for ( i = 0; i < 90; i++) {247 for (uint i = 0; i < 90; i++) { 251 248 if (!scumm_stricmp(baseName, _sequenceList[i])) 252 249 _sequenceNum = i; 253 250 } 254 251 } 255 252 256 sprintf(videoName,"%s.dxa", baseName);253 Common::String videoName = Common::String::printf("%s.dxa", baseName); 257 254 if (!loadFile(videoName)) 258 error("Failed to load video file %s", videoName );255 error("Failed to load video file %s", videoName.c_str()); 259 256 260 debug(0, "Playing video %s", videoName );257 debug(0, "Playing video %s", videoName.c_str()); 261 258 262 259 CursorMan.showMouse(false); 263 260 261 _firstFrameOffset = _fileStream->pos(); 262 264 263 return true; 265 264 } 266 265 266 void 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 267 284 void MoviePlayerDXA::playVideo() { 268 285 // Most of the videos included in the Amiga version, reduced the 269 286 // resoluton to 384 x 280, so require the screen to be cleared, … … 272 289 _vm->clearSurfaces(); 273 290 } 274 291 275 while ( getCurFrame() < getFrameCount() && !_skipMovie && !_vm->shouldQuit())292 while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit()) 276 293 handleNextFrame(); 277 294 } 278 295 279 296 void MoviePlayerDXA::stopVideo() { 280 close File();297 close(); 281 298 _mixer->stopHandle(_bgSound); 282 299 } 283 300 … … 318 335 } 319 336 320 337 void 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()) { 322 339 copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); 323 340 return; 324 341 } 325 342 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; 329 346 startSound(); 330 347 } 331 348 332 if (getCurFrame() < getFrameCount()) { 333 decodeNextFrame(); 334 if (_vm->_interactiveVideo == TYPE_OMNITV) { 349 if (!endOfVideo()) { 350 if (_vm->_interactiveVideo == TYPE_OMNITV) 335 351 copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); 336 } else if (_vm->_interactiveVideo == TYPE_LOOPING) {352 else if (_vm->_interactiveVideo == TYPE_LOOPING) 337 353 copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); 338 }339 354 } else if (_vm->_interactiveVideo == TYPE_OMNITV) { 340 close File();355 close(); 341 356 _vm->_interactiveVideo = 0; 342 357 _vm->_variableArray[254] = 6747; 343 358 } 344 359 } 345 360 346 361 void MoviePlayerDXA::handleNextFrame() { 347 decodeNextFrame();348 362 if (processFrame()) 349 363 _vm->_system->updateScreen(); 350 364 351 365 MoviePlayer::handleNextFrame(); 352 366 } 353 367 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 368 368 bool MoviePlayerDXA::processFrame() { 369 369 Graphics::Surface *screen = _vm->_system->lockScreen(); 370 370 copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); … … 381 381 // sync case for the subsequent frames. 382 382 _ticks = _vm->_system->getMillis(); 383 383 } else { 384 _ticks += get FrameWaitTime();384 _ticks += getTimeToNextFrame(); 385 385 while (_vm->_system->getMillis() < _ticks) 386 386 _vm->_system->delayMillis(10); 387 387 } … … 407 407 } 408 408 409 409 bool MoviePlayerSMK::load() { 410 char videoName[20];410 Common::String videoName = Common::String::printf("%s.smk", baseName); 411 411 412 sprintf(videoName, "%s.smk", baseName);413 412 if (!loadFile(videoName)) 414 error("Failed to load video file %s", videoName );413 error("Failed to load video file %s", videoName.c_str()); 415 414 416 debug(0, "Playing video %s", videoName );415 debug(0, "Playing video %s", videoName.c_str()); 417 416 418 417 CursorMan.showMouse(false); 419 418 419 _firstFrameOffset = _fileStream->pos(); 420 420 421 return true; 421 422 } 422 423 424 void 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 423 442 void MoviePlayerSMK::playVideo() { 424 while ( getCurFrame() < getFrameCount() && !_skipMovie && !_vm->shouldQuit())443 while (!endOfVideo() && !_skipMovie && !_vm->shouldQuit()) 425 444 handleNextFrame(); 426 445 } 427 446 428 447 void MoviePlayerSMK::stopVideo() { 429 close File();448 close(); 430 449 } 431 450 432 451 void MoviePlayerSMK::startSound() { 433 452 } 434 453 435 454 void MoviePlayerSMK::handleNextFrame() { 436 decodeNextFrame();437 455 processFrame(); 438 456 439 457 MoviePlayer::handleNextFrame(); 440 458 } 441 459 442 460 void 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; 446 464 } 447 465 448 if (getCurFrame() < getFrameCount()) { 449 decodeNextFrame(); 466 if (!endOfVideo()) { 450 467 if (_vm->_interactiveVideo == TYPE_OMNITV) { 451 468 copyFrameToBuffer(_vm->getBackBuf(), 465, 222, _vm->_screenWidth); 452 469 } else if (_vm->_interactiveVideo == TYPE_LOOPING) { 453 470 copyFrameToBuffer(_vm->getBackBuf(), (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); 454 471 } 455 472 } else if (_vm->_interactiveVideo == TYPE_OMNITV) { 456 close File();473 close(); 457 474 _vm->_interactiveVideo = 0; 458 475 _vm->_variableArray[254] = 6747; 459 476 } 460 477 } 461 478 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 476 479 bool MoviePlayerSMK::processFrame() { 477 480 Graphics::Surface *screen = _vm->_system->lockScreen(); 478 481 copyFrameToBuffer((byte *)screen->pixels, (_vm->_screenWidth - getWidth()) / 2, (_vm->_screenHeight - getHeight()) / 2, _vm->_screenWidth); 479 482 _vm->_system->unlockScreen(); 480 483 481 uint32 waitTime = get FrameWaitTime();484 uint32 waitTime = getTimeToNextFrame(); 482 485 483 if (!waitTime) {484 warning("dropped frame %i", getCurFrame());485 return false;486 }487 488 486 _vm->_system->updateScreen(); 489 487 490 488 // Wait before showing the next frame -
graphics/module.mk
26 26 video/flic_decoder.o \ 27 27 video/mpeg_player.o \ 28 28 video/smk_decoder.o \ 29 video/video_ player.o \29 video/video_decoder.o \ 30 30 video/codecs/msrle.o \ 31 31 video/codecs/msvideo1.o \ 32 32 video/coktelvideo/indeo3.o \ -
graphics/video/video_decoder.h
30 30 #include "common/list.h" 31 31 #include "common/stream.h" 32 32 33 #include "graphics/surface.h" 34 #include "graphics/pixelformat.h" 35 33 36 namespace Common { 34 37 class SeekableReadStream; 35 38 } … … 42 45 class VideoDecoder { 43 46 public: 44 47 VideoDecoder(); 45 virtual ~VideoDecoder() ;48 virtual ~VideoDecoder() {} 46 49 47 50 /** 48 51 * Returns the width of the video 49 52 * @return the width of the video 50 53 */ 51 virtual int getWidth();54 virtual uint16 getWidth() const = 0; 52 55 53 56 /** 54 57 * Returns the height of the video 55 58 * @return the height of the video 56 59 */ 57 virtual int getHeight();60 virtual uint16 getHeight() const = 0; 58 61 59 62 /** 60 63 * Returns the current frame number of the video 61 * @return the current frame number ofthe video64 * @return the last frame decoded by the video 62 65 */ 63 virtual int32 getCurFrame() ;66 virtual int32 getCurFrame() const { return _curFrame; } 64 67 65 68 /** 66 69 * Returns the amount of frames in the video 67 70 * @return the amount of frames in the video 68 71 */ 69 virtual int32 getFrameCount();72 virtual uint32 getFrameCount() const = 0; 70 73 71 74 /** 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 74 76 */ 75 virtual int32 getFrameRate();77 virtual uint32 getElapsedTime() const; 76 78 77 79 /** 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 80 82 */ 81 virtual int32 getFrameDelay();83 virtual bool needsUpdate() const; 82 84 83 85 /** 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 88 88 */ 89 virtual int32 getAudioLag();89 virtual bool loadFile(const Common::String &filename); 90 90 91 91 /** 92 * Returns the time to wait until the next frame in ms, minding any lag93 * @return the time to wait until the next frame in ms94 */95 virtual uint32 getFrameWaitTime();96 97 /**98 92 * Load a video file 99 * @param filename the filenameto load93 * @param stream the stream to load 100 94 */ 101 virtual bool load File(const char *filename) = 0;95 virtual bool load(Common::SeekableReadStream &stream) = 0; 102 96 103 97 /** 104 98 * Close a video file 105 99 */ 106 virtual void close File() = 0;100 virtual void close() = 0; 107 101 108 102 /** 109 103 * Returns if a video file is loaded or not 110 104 */ 111 bool isVideoLoaded() { return (_fileStream != NULL); }105 virtual bool isVideoLoaded() const = 0; 112 106 113 107 /** 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 116 111 */ 117 virtual void setPalette(byte *pal);112 virtual Surface *decodeNextFrame() = 0; 118 113 119 114 /** 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 125 116 */ 126 byte getPixel(int x, int y) { 127 return *(_videoFrameBuffer + y * _videoInfo.width + x * 1); 128 } 117 virtual PixelFormat getPixelFormat() const = 0; 129 118 130 119 /** 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) 133 121 */ 134 byte getPixel(int offset) { return getPixel(offset, 0); }122 virtual byte *getPalette() { return 0; } 135 123 136 124 /** 137 * Return the black palette color for the current frame125 * Returns if the palette is dirty or not 138 126 */ 139 byte getBlack() { return _curFrameBlack; }127 virtual bool hasDirtyPalette() const { return false; } 140 128 141 129 /** 142 * Return the white palette color for the current frame130 * Add the time the video has been paused to maintain sync 143 131 */ 144 byte getWhite() { return _curFrameWhite; }132 virtual void addPauseTime(uint32 ms) { _startTime += ms; } 145 133 146 134 /** 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 153 136 */ 154 v oid copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);137 virtual bool endOfVideo() const; 155 138 156 139 /** 157 * Decode the next frame to _videoFrameBuffer140 * Set the current palette to the system palette 158 141 */ 159 v irtual bool decodeNextFrame() = 0;142 void setSystemPalette(); 160 143 144 /** 145 * Return the time until the next frame (in ms) 146 */ 147 virtual uint32 getTimeToNextFrame() const = 0; 148 161 149 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; 150 /** 151 * Resets _curFrame and _startTime. Should be called from every close() function. 152 */ 153 void reset(); 172 154 173 byte _curFrameBlack, _curFrameWhite; 174 175 Common::SeekableReadStream *_fileStream; 176 byte *_videoFrameBuffer; 155 int32 _curFrame; 156 uint32 _startTime; 177 157 }; 178 158 179 class VideoPlayer { 159 /** 160 * A VideoDecoder wrapper that implements getTimeToNextFrame() based on getFrameRate(). 161 */ 162 class FixedRateVideoDecoder : public VideoDecoder { 180 163 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); 164 FixedRateVideoDecoder() {} 165 virtual ~FixedRateVideoDecoder() {} 194 166 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; 200 168 201 169 protected: 202 170 /** 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. 205 174 */ 206 virtual void performPostProcessing(byte *screen);175 virtual double getFrameRate() const = 0; 207 176 208 bool _skipVideo; 209 VideoDecoder* _decoder; 210 211 void processVideoEvents(Common::List<Common::Event> &stopEvents); 177 private: 178 uint32 getFrameBeginTime(uint32 frame) const; 212 179 }; 213 180 214 181 } // End of namespace Graphics -
graphics/video/dxa_decoder.cpp
39 39 40 40 DXADecoder::DXADecoder() { 41 41 _fileStream = 0; 42 _surface = 0; 43 _dirtyPalette = false; 42 44 43 45 _frameBuffer1 = 0; 44 46 _frameBuffer2 = 0; 45 47 _scaledBuffer = 0; 46 _videoFrameBuffer = 0;47 48 48 49 _inBuffer = 0; 49 50 _inBufferSize = 0; … … 51 52 _decompBuffer = 0; 52 53 _decompBufferSize = 0; 53 54 54 _ videoInfo.width = 0;55 _ videoInfo.height = 0;55 _width = 0; 56 _height = 0; 56 57 57 58 _frameSize = 0; 58 _videoInfo.frameCount = 0; 59 _videoInfo.currentFrame = 0; 60 _videoInfo.frameRate = 0; 61 _videoInfo.frameDelay = 0; 59 _frameCount = 0; 60 _frameRate = 0; 62 61 63 62 _scaleMode = S_NONE; 64 63 } 65 64 66 65 DXADecoder::~DXADecoder() { 67 close File();66 close(); 68 67 } 69 68 70 bool DXADecoder::loadFile(const char *fileName) { 71 uint32 tag; 72 int32 frameRate; 69 bool DXADecoder::load(Common::SeekableReadStream &stream) { 70 close(); 73 71 74 closeFile();72 _fileStream = &stream; 75 73 76 _fileStream = SearchMan.createReadStreamForMember(fileName); 77 if (!_fileStream) 78 return false; 79 80 tag = _fileStream->readUint32BE(); 74 uint32 tag = _fileStream->readUint32BE(); 81 75 assert(tag == MKID_BE('DEXA')); 82 76 83 77 uint8 flags = _fileStream->readByte(); 84 _ videoInfo.frameCount = _fileStream->readUint16BE();85 frameRate = _fileStream->readSint32BE();78 _frameCount = _fileStream->readUint16BE(); 79 int32 frameRate = _fileStream->readSint32BE(); 86 80 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; 97 87 98 _ videoInfo.width = _fileStream->readUint16BE();99 _ videoInfo.height = _fileStream->readUint16BE();88 _width = _fileStream->readUint16BE(); 89 _height = _fileStream->readUint16BE(); 100 90 101 91 if (flags & 0x80) { 102 92 _scaleMode = S_INTERLACED; 103 _curHeight = _ videoInfo.height / 2;93 _curHeight = _height / 2; 104 94 } else if (flags & 0x40) { 105 95 _scaleMode = S_DOUBLE; 106 _curHeight = _ videoInfo.height / 2;96 _curHeight = _height / 2; 107 97 } else { 108 98 _scaleMode = S_NONE; 109 _curHeight = _ videoInfo.height;99 _curHeight = _height; 110 100 } 111 101 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; 113 104 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; 115 108 _decompBufferSize = _frameSize; 116 109 _frameBuffer1 = (uint8 *)malloc(_frameSize); 117 110 memset(_frameBuffer1, 0, _frameSize); … … 135 128 136 129 do { 137 130 tag = _fileStream->readUint32BE(); 138 if (tag != 0) { 131 132 if (tag != 0) 139 133 size = _fileStream->readUint32BE(); 140 } 134 141 135 switch (tag) { 142 136 case 0: // No more tags 143 137 break; … … 159 153 // Read the sound header 160 154 _soundTag = _fileStream->readUint32BE(); 161 155 162 _videoInfo.currentFrame = 0;163 164 _videoInfo.firstframeOffset = _fileStream->pos();165 166 156 return true; 167 157 } 168 158 169 void DXADecoder::close File() {159 void DXADecoder::close() { 170 160 if (!_fileStream) 171 161 return; 172 162 173 163 delete _fileStream; 174 164 _fileStream = 0; 175 165 166 delete _surface; 167 _surface = 0; 168 176 169 free(_frameBuffer1); 177 170 free(_frameBuffer2); 178 171 free(_scaledBuffer); … … 181 174 182 175 _inBuffer = 0; 183 176 _decompBuffer = 0; 177 178 reset(); 184 179 } 185 180 186 181 void DXADecoder::decodeZlib(byte *data, int size, int totalSize) { … … 208 203 209 204 memcpy(_frameBuffer2, _frameBuffer1, _frameSize); 210 205 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) { 213 208 byte type = *dat++; 214 byte *b2 = _frameBuffer1 + bx + by * _ videoInfo.width;209 byte *b2 = _frameBuffer1 + bx + by * _width; 215 210 216 211 switch (type) { 217 212 case 0: … … 243 238 } 244 239 diffMap <<= 1; 245 240 } 246 b2 += _ videoInfo.width;241 b2 += _width; 247 242 } 248 243 break; 249 244 } … … 254 249 for (int xc = 0; xc < BLOCKW; xc++) { 255 250 b2[xc] = color; 256 251 } 257 b2 += _ videoInfo.width;252 b2 += _width; 258 253 } 259 254 break; 260 255 } … … 263 258 for (int xc = 0; xc < BLOCKW; xc++) { 264 259 b2[xc] = *dat++; 265 260 } 266 b2 += _ videoInfo.width;261 b2 += _width; 267 262 } 268 263 break; 269 264 } … … 275 270 int my = mbyte & 0x07; 276 271 if (mbyte & 0x08) 277 272 my = -my; 278 byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _ videoInfo.width;273 byte *b1 = _frameBuffer2 + (bx+mx) + (by+my) * _width; 279 274 for (int yc = 0; yc < BLOCKH; yc++) { 280 275 memcpy(b2, b1, BLOCKW); 281 b1 += _ videoInfo.width;282 b2 += _ videoInfo.width;276 b1 += _width; 277 b2 += _width; 283 278 } 284 279 break; 285 280 } … … 309 304 310 305 memcpy(_frameBuffer2, _frameBuffer1, _frameSize); 311 306 312 int codeSize = _ videoInfo.width * _curHeight / 16;307 int codeSize = _width * _curHeight / 16; 313 308 int dataSize, motSize, maskSize; 314 309 315 310 dataSize = READ_BE_UINT32(&_decompBuffer[0]); … … 322 317 maskBuf = &motBuf[motSize]; 323 318 324 319 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) { 326 321 uint8 type = *codeBuf++; 327 uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _ videoInfo.width;322 uint8 *b2 = (uint8*)_frameBuffer1 + bx + by * _width; 328 323 329 324 switch (type) { 330 325 case 0: … … 341 336 } 342 337 diffMap <<= 1; 343 338 } 344 b2 += _ videoInfo.width;339 b2 += _width; 345 340 } 346 341 break; 347 342 } … … 352 347 for (int xc = 0; xc < BLOCKW; xc++) { 353 348 b2[xc] = color; 354 349 } 355 b2 += _ videoInfo.width;350 b2 += _width; 356 351 } 357 352 break; 358 353 } … … 361 356 for (int xc = 0; xc < BLOCKW; xc++) { 362 357 b2[xc] = *dataBuf++; 363 358 } 364 b2 += _ videoInfo.width;359 b2 += _width; 365 360 } 366 361 break; 367 362 } … … 375 370 if (mbyte & 0x08) 376 371 my = -my; 377 372 378 uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _ videoInfo.width;373 uint8 *b1 = (uint8*)_frameBuffer2 + (bx+mx) + (by+my) * _width; 379 374 for (int yc = 0; yc < BLOCKH; yc++) { 380 375 memcpy(b2, b1, BLOCKW); 381 b1 += _ videoInfo.width;382 b2 += _ videoInfo.width;376 b1 += _width; 377 b2 += _width; 383 378 } 384 379 break; 385 380 } … … 391 386 392 387 for (int subBlock = 0; subBlock < 4; subBlock++) { 393 388 int sx = bx + subX[subBlock], sy = by + subY[subBlock]; 394 b2 = (uint8*)_frameBuffer1 + sx + sy * _ videoInfo.width;389 b2 = (uint8*)_frameBuffer1 + sx + sy * _width; 395 390 switch (subMask & 0xC0) { 396 391 // 00: skip 397 392 case 0x00: … … 403 398 for (int xc = 0; xc < BLOCKW / 2; xc++) { 404 399 b2[xc] = subColor; 405 400 } 406 b2 += _ videoInfo.width;401 b2 += _width; 407 402 } 408 403 break; 409 404 } … … 419 414 if (mbyte & 0x08) 420 415 my = -my; 421 416 422 uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _ videoInfo.width;417 uint8 *b1 = (uint8*)_frameBuffer2 + (sx+mx) + (sy+my) * _width; 423 418 for (int yc = 0; yc < BLOCKH / 2; yc++) { 424 419 memcpy(b2, b1, BLOCKW / 2); 425 b1 += _ videoInfo.width;426 b2 += _ videoInfo.width;420 b1 += _width; 421 b2 += _width; 427 422 } 428 423 break; 429 424 } … … 433 428 for (int xc = 0; xc < BLOCKW / 2; xc++) { 434 429 b2[xc] = *dataBuf++; 435 430 } 436 b2 += _ videoInfo.width;431 b2 += _width; 437 432 } 438 433 break; 439 434 } … … 458 453 b2[xc] = pixels[code & 1]; 459 454 code >>= 1; 460 455 } 461 b2 += _ videoInfo.width;456 b2 += _width; 462 457 } 463 458 } else { 464 459 uint32 code = READ_BE_UINT32(maskBuf); … … 468 463 b2[xc] = pixels[code & 3]; 469 464 code >>= 2; 470 465 } 471 b2 += _ videoInfo.width;466 b2 += _width; 472 467 } 473 468 } 474 469 break; … … 481 476 #endif 482 477 } 483 478 484 bool DXADecoder::decodeNextFrame() { 485 uint32 tag; 486 487 if (_videoInfo.currentFrame == 0) 488 _videoInfo.startTime = g_system->getMillis(); 489 490 tag = _fileStream->readUint32BE(); 479 Surface *DXADecoder::decodeNextFrame() { 480 uint32 tag = _fileStream->readUint32BE(); 491 481 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; 496 484 } 497 485 498 486 tag = _fileStream->readUint32BE(); … … 529 517 530 518 if (type == 3) { 531 519 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; 534 522 _frameBuffer1[offs] ^= _frameBuffer2[offs]; 535 523 } 536 524 } … … 540 528 switch (_scaleMode) { 541 529 case S_INTERLACED: 542 530 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); 545 533 } 546 _ videoFrameBuffer= _scaledBuffer;534 _surface->pixels = _scaledBuffer; 547 535 break; 548 536 case S_DOUBLE: 549 537 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); 552 540 } 553 _ videoFrameBuffer= _scaledBuffer;541 _surface->pixels = _scaledBuffer; 554 542 break; 555 543 case S_NONE: 556 _ videoFrameBuffer= _frameBuffer1;544 _surface->pixels = _frameBuffer1; 557 545 break; 558 546 } 559 547 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; 561 559 } 562 560 563 561 } // End of namespace Graphics -
graphics/video/flic_decoder.cpp
34 34 FlicDecoder::FlicDecoder() { 35 35 _paletteChanged = false; 36 36 _fileStream = 0; 37 _videoFrameBuffer = 0; 38 memset(&_videoInfo, 0, sizeof(_videoInfo)); 37 _surface = 0; 39 38 } 40 39 41 40 FlicDecoder::~FlicDecoder() { 42 close File();41 close(); 43 42 } 44 43 45 bool FlicDecoder::load File(const char *fileName) {46 close File();44 bool FlicDecoder::load(Common::SeekableReadStream &stream) { 45 close(); 47 46 48 _fileStream = SearchMan.createReadStreamForMember(fileName); 49 if (!_fileStream) 50 return false; 47 _fileStream = &stream; 51 48 52 49 /* uint32 frameSize = */ _fileStream->readUint32LE(); 53 50 uint16 frameType = _fileStream->readUint16LE(); … … 60 57 return false; 61 58 } 62 59 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(); 66 64 uint16 colorDepth = _fileStream->readUint16LE(); 67 65 if (colorDepth != 8) { 68 66 warning("FlicDecoder::FlicDecoder(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", frameType); … … 70 68 _fileStream = 0; 71 69 return false; 72 70 } 71 73 72 _fileStream->readUint16LE(); // flags 74 73 // Note: The normal delay is a 32-bit integer (dword), whereas the overriden delay is a 16-bit integer (word) 75 74 // 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; 78 77 79 78 _fileStream->seek(80); 80 79 _offsetFrame1 = _fileStream->readUint32LE(); 81 80 _offsetFrame2 = _fileStream->readUint32LE(); 82 81 83 _videoFrameBuffer = new byte[_videoInfo.width * _videoInfo.height]; 82 _surface = new Graphics::Surface(); 83 _surface->create(width, height, 1); 84 84 _palette = (byte *)malloc(3 * 256); 85 85 memset(_palette, 0, 3 * 256); 86 86 _paletteChanged = false; 87 87 88 88 // Seek to the first frame 89 _videoInfo.currentFrame = 0;90 89 _fileStream->seek(_offsetFrame1); 91 90 return true; 92 91 } 93 92 94 void FlicDecoder::close File() {93 void FlicDecoder::close() { 95 94 if (!_fileStream) 96 95 return; 97 96 98 97 delete _fileStream; 99 98 _fileStream = 0; 100 99 101 delete[] _videoFrameBuffer; 102 _videoFrameBuffer = 0; 100 _surface->free(); 101 delete _surface; 102 _surface = 0; 103 103 104 104 free(_palette); 105 _dirtyRects.clear(); 105 106 106 _dirtyRects.clear();107 reset(); 107 108 } 108 109 109 110 void 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())) { 112 113 int chunks = *data++; 113 114 while (chunks--) { 114 115 int count = (int8)*data++; … … 125 126 126 127 // Redraw 127 128 _dirtyRects.clear(); 128 _dirtyRects.push_back(Common::Rect(0, 0, _videoInfo.width, _videoInfo.height));129 _dirtyRects.push_back(Common::Rect(0, 0, getWidth(), getHeight())); 129 130 } 130 131 131 132 #define OP_PACKETCOUNT 0 … … 152 153 case OP_UNDEFINED: 153 154 break; 154 155 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)); 157 158 break; 158 159 case OP_LINESKIPCOUNT: 159 160 currentLine += -(int16)opcode; … … 168 169 column += *data++; 169 170 int rleCount = (int8)*data++; 170 171 if (rleCount > 0) { 171 memcpy( _videoFrameBuffer + (currentLine * _videoInfo.width) + column, data, rleCount * 2);172 memcpy((byte *)_surface->pixels + (currentLine * getWidth()) + column, data, rleCount * 2); 172 173 data += rleCount * 2; 173 174 _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); 174 175 } else if (rleCount < 0) { 175 176 rleCount = -rleCount; 176 177 uint16 dataWord = READ_UINT16(data); data += 2; 177 178 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); 179 180 } 180 181 _dirtyRects.push_back(Common::Rect(column, currentLine, column + rleCount * 2, currentLine + 1)); 181 182 } else { // End of cutscene ? … … 194 195 #define PSTAMP 18 195 196 #define FRAME_TYPE 0xF1FA 196 197 197 bool FlicDecoder::decodeNextFrame() { 198 if (_videoInfo.currentFrame == 0) 199 _videoInfo.startTime = g_system->getMillis(); 200 198 Surface *FlicDecoder::decodeNextFrame() { 201 199 // Read chunk 202 200 uint32 frameSize = _fileStream->readUint32LE(); 203 201 uint16 frameType = _fileStream->readUint16LE(); 204 202 uint16 chunkCount = 0; 205 203 206 204 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. 223 209 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 } 225 232 } 226 233 break; 227 234 default: … … 239 246 switch (frameType) { 240 247 case FLI_SETPAL: 241 248 unpackPalette(data); 242 setPalette(_palette);243 249 _paletteChanged = true; 244 250 break; 245 251 case FLI_SS2: … … 259 265 delete[] data; 260 266 } 261 267 } 268 269 _curFrame++; 262 270 271 if (_curFrame == 0) 272 _startTime = g_system->getMillis(); 273 263 274 // 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; 266 277 _fileStream->seek(_offsetFrame2); 267 278 } 268 279 269 return _ videoInfo.currentFrame < _videoInfo.frameCount;280 return _surface; 270 281 } 271 282 272 283 void FlicDecoder::reset() { 273 _videoInfo.currentFrame = 0; 274 _fileStream->seek(_offsetFrame1); 284 VideoDecoder::reset(); 285 if (_fileStream) 286 _fileStream->seek(_offsetFrame1); 275 287 } 276 288 277 289 void FlicDecoder::unpackPalette(uint8 *data) { … … 303 315 for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) { 304 316 for (int y = (*it).top; y < (*it).bottom; ++y) { 305 317 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); 307 319 } 308 320 } 309 321 _dirtyRects.clear(); -
graphics/video/avi_decoder.cpp
23 23 * 24 24 */ 25 25 26 #include "common/archive.h"27 26 #include "common/endian.h" 28 27 #include "common/file.h" 29 28 #include "common/stream.h" … … 47 46 _videoCodec = NULL; 48 47 _decodedHeader = false; 49 48 _audStream = NULL; 50 _ fileStream = NULL;49 _stream = NULL; 51 50 _audHandle = new Audio::SoundHandle(); 51 _dirtyPalette = false; 52 _stream = NULL; 52 53 memset(_palette, 0, sizeof(_palette)); 53 54 memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT)); 54 55 memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER)); … … 58 59 } 59 60 60 61 AviDecoder::~AviDecoder() { 61 close File();62 close(); 62 63 delete _audHandle; 63 64 } 64 65 65 66 void AviDecoder::runHandle(uint32 tag) { 66 assert (_ fileStream);67 if (_ fileStream->eos())67 assert (_stream); 68 if (_stream->eos()) 68 69 return; 69 70 70 71 debug (3, "Decoding tag %s", tag2str(tag)); 71 72 72 73 switch (tag) { 73 74 case ID_RIFF: 74 /*_filesize = */_ fileStream->readUint32LE();75 if (_ fileStream->readUint32BE() != ID_AVI)75 /*_filesize = */_stream->readUint32LE(); 76 if (_stream->readUint32BE() != ID_AVI) 76 77 error("RIFF file is not an AVI video"); 77 78 break; 78 79 case ID_LIST: 79 80 handleList(); 80 81 break; 81 82 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(); 93 94 //Ignore 16 bytes of reserved data 94 _ fileStream->skip(16);95 _stream->skip(16); 95 96 break; 96 97 case ID_STRH: 97 98 handleStreamHeader(); … … 100 101 case ID_VEDT: // Unknown, safe to ignore 101 102 case ID_JUNK: // Alignment bytes, should be ignored 102 103 { 103 uint32 junkSize = _ fileStream->readUint32LE();104 _ fileStream->skip(junkSize + (junkSize & 1)); // Alignment104 uint32 junkSize = _stream->readUint32LE(); 105 _stream->skip(junkSize + (junkSize & 1)); // Alignment 105 106 } break; 106 107 case ID_IDX1: 107 _ixInfo.size = _ fileStream->readUint32LE();108 _ixInfo.size = _stream->readUint32LE(); 108 109 _ixInfo.indices = new AVIOLDINDEX::Index[_ixInfo.size / 16]; 109 110 debug (0, "%d Indices", (_ixInfo.size / 16)); 110 111 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(); 115 116 debug (0, "Index %d == Tag \'%s\', Offset = %d, Size = %d", i, tag2str(_ixInfo.indices[i].id), _ixInfo.indices[i].offset, _ixInfo.indices[i].size); 116 117 } 117 118 break; … … 121 122 } 122 123 123 124 void AviDecoder::handleList() { 124 uint32 listSize = _ fileStream->readUint32LE() - 4; // Subtract away listType's 4 bytes125 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(); 127 128 128 129 debug (0, "Found LIST of type %s", tag2str(listType)); 129 130 130 while ((_ fileStream->pos() - curPos) < listSize)131 runHandle(_ fileStream->readUint32BE());131 while ((_stream->pos() - curPos) < listSize) 132 runHandle(_stream->readUint32BE()); 132 133 133 134 // We now have all the header data 134 135 if (listType == ID_HDRL) … … 137 138 138 139 void AviDecoder::handleStreamHeader() { 139 140 AVIStreamHeader sHeader; 140 sHeader.size = _ fileStream->readUint32LE();141 sHeader.streamType = _ fileStream->readUint32BE();141 sHeader.size = _stream->readUint32LE(); 142 sHeader.streamType = _stream->readUint32BE(); 142 143 if (sHeader.streamType == ID_MIDS || sHeader.streamType == ID_TXTS) 143 144 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(); 160 161 161 if (_ fileStream->readUint32BE() != ID_STRF)162 if (_stream->readUint32BE() != ID_STRF) 162 163 error("Could not find STRF tag"); 163 /* uint32 strfSize = */ _ fileStream->readUint32LE();164 /* uint32 strfSize = */ _stream->readUint32LE(); 164 165 165 166 if (sHeader.streamType == ID_VIDS) { 166 167 _vidsHeader = sHeader; 167 168 168 _bmInfo.size = _ fileStream->readUint32LE();169 _bmInfo.width = _ fileStream->readUint32LE();169 _bmInfo.size = _stream->readUint32LE(); 170 _bmInfo.width = _stream->readUint32LE(); 170 171 assert (_header.width == _bmInfo.width); 171 _bmInfo.height = _ fileStream->readUint32LE();172 _bmInfo.height = _stream->readUint32LE(); 172 173 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(); 181 182 182 183 if (_bmInfo.bitCount == 8) { 183 184 if (_bmInfo.clrUsed == 0) 184 185 _bmInfo.clrUsed = 256; 185 186 186 187 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(); 191 192 } 192 193 193 setPalette(_palette);194 _dirtyPalette = true; 194 195 } 195 196 } else if (sHeader.streamType == ID_AUDS) { 196 197 _audsHeader = sHeader; 197 198 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(); 204 205 } 205 206 } 206 207 207 bool AviDecoder::load File(const char *fileName) {208 close File();208 bool AviDecoder::load(Common::SeekableReadStream &stream) { 209 close(); 209 210 210 _fileStream = SearchMan.createReadStreamForMember(fileName); 211 if (!_fileStream) 212 return false; 213 211 _stream = &stream; 214 212 _decodedHeader = false; 215 // Seek to the first frame216 _videoInfo.currentFrame = 0;217 213 218 219 214 // Read chunks until we have decoded the header 220 215 while (!_decodedHeader) 221 runHandle(_ fileStream->readUint32BE());216 runHandle(_stream->readUint32BE()); 222 217 223 _videoFrameBuffer = new byte[_header.width * _header.height]; 224 memset(_videoFrameBuffer, 0, _header.width * _header.height); 218 uint32 nextTag = _stream->readUint32BE(); 225 219 226 uint32 nextTag = _fileStream->readUint32BE();227 228 220 // Throw out any JUNK section 229 221 if (nextTag == ID_JUNK) { 230 222 runHandle(ID_JUNK); 231 nextTag = _ fileStream->readUint32BE();223 nextTag = _stream->readUint32BE(); 232 224 } 233 225 234 226 // Ignore the 'movi' LIST 235 227 if (nextTag == ID_LIST) { 236 _ fileStream->readUint32BE(); // Skip size237 if (_ fileStream->readUint32BE() != ID_MOVI)228 _stream->readUint32BE(); // Skip size 229 if (_stream->readUint32BE() != ID_MOVI) 238 230 error ("Expected 'movi' LIST"); 239 231 } else 240 232 error ("Expected 'movi' LIST"); … … 248 240 _mixer->playInputStream(_soundType, _audHandle, _audStream); 249 241 250 242 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); 252 244 if ((_audsHeader.scale != 0) && (_header.flags & AVIF_ISINTERLEAVED)) 253 245 debug (0, "Sound Rate = %d", AUDIO_RATE); 254 246 debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler)); 255 247 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 here261 _videoInfo.frameDelay = _header.microSecondsPerFrame / 10;262 263 248 if (!_videoCodec) 264 249 return false; 265 250 266 251 return true; 267 252 } 268 253 269 void AviDecoder::close File() {270 if (!_ fileStream)254 void AviDecoder::close() { 255 if (!_stream) 271 256 return; 272 257 273 delete _ fileStream;274 _ fileStream = 0;258 delete _stream; 259 _stream = 0; 275 260 276 delete[] _videoFrameBuffer;277 _videoFrameBuffer = 0;278 279 261 // Deinitialize sound 280 262 _mixer->stopHandle(*_audHandle); 281 263 _audStream = 0; … … 294 276 memset(&_vidsHeader, 0, sizeof(AVIStreamHeader)); 295 277 memset(&_audsHeader, 0, sizeof(AVIStreamHeader)); 296 278 memset(&_ixInfo, 0, sizeof(AVIOLDINDEX)); 279 280 reset(); 297 281 } 298 282 299 Surface *AviDecoder::getNextFrame() { 300 uint32 nextTag = _fileStream->readUint32BE(); 283 uint32 AviDecoder::getElapsedTime() const { 284 if (_audStream) 285 return _mixer->getSoundElapsedTime(*_audHandle); 301 286 302 if (_fileStream->eos()) 287 return VideoDecoder::getElapsedTime(); 288 } 289 290 Surface *AviDecoder::decodeNextFrame() { 291 uint32 nextTag = _stream->readUint32BE(); 292 293 if (_stream->eos()) 303 294 return NULL; 304 295 296 if (_curFrame == -1) 297 _startTime = g_system->getMillis(); 298 305 299 if (nextTag == ID_LIST) { 306 300 // 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(); 309 303 310 if (_ fileStream->readUint32BE() != ID_REC)304 if (_stream->readUint32BE() != ID_REC) 311 305 error ("Expected 'rec ' LIST"); 312 306 313 307 // Decode chunks in the list and see if we get a frame 314 308 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(); 317 311 if (temp) 318 312 frame = temp; 319 313 } … … 321 315 return frame; 322 316 } else if (getStreamType(nextTag) == 'wb') { 323 317 // Audio Chunk 324 uint32 chunkSize = _ fileStream->readUint32LE();318 uint32 chunkSize = _stream->readUint32LE(); 325 319 byte *data = (byte *)malloc(chunkSize); 326 _ fileStream->read(data, chunkSize);320 _stream->read(data, chunkSize); 327 321 328 322 byte flags = 0; 329 323 if (_audsHeader.sampleSize == 2) … … 332 326 flags |= Audio::FLAG_UNSIGNED; 333 327 334 328 _audStream->queueBuffer(data, chunkSize, DisposeAfterUse::YES, flags); 335 _ fileStream->skip(chunkSize & 1); // Alignment329 _stream->skip(chunkSize & 1); // Alignment 336 330 } else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' || 337 331 getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32') { 338 332 // Compressed Frame 339 _ videoInfo.currentFrame++;340 uint32 chunkSize = _ fileStream->readUint32LE();333 _curFrame++; 334 uint32 chunkSize = _stream->readUint32LE(); 341 335 342 336 if (chunkSize == 0) // Keep last frame on screen 343 337 return NULL; 344 338 345 Common::SeekableReadStream *frameData = _ fileStream->readStream(chunkSize);339 Common::SeekableReadStream *frameData = _stream->readStream(chunkSize); 346 340 Graphics::Surface *surface = _videoCodec->decodeImage(frameData); 347 341 delete frameData; 348 _ fileStream->skip(chunkSize & 1); // Alignment342 _stream->skip(chunkSize & 1); // Alignment 349 343 return surface; 350 344 } else if (getStreamType(nextTag) == 'pc') { 351 345 // Palette Change 352 _ fileStream->readUint32LE(); // Chunk size, not needed here353 byte firstEntry = _ fileStream->readByte();354 uint16 numEntries = _ fileStream->readByte();355 _ fileStream->readUint16LE(); // Reserved346 _stream->readUint32LE(); // Chunk size, not needed here 347 byte firstEntry = _stream->readByte(); 348 uint16 numEntries = _stream->readByte(); 349 _stream->readUint16LE(); // Reserved 356 350 357 351 // 0 entries means all colors are going to be changed 358 352 if (numEntries == 0) 359 353 numEntries = 256; 360 354 361 355 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 purpose356 _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 366 360 } 367 361 368 setPalette(_palette);362 _dirtyPalette = true; 369 363 370 364 // No alignment necessary. It's always even. 371 365 } else if (nextTag == ID_JUNK) { … … 373 367 } else if (nextTag == ID_IDX1) { 374 368 runHandle(ID_IDX1); 375 369 } else 376 error ("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());370 error("Tag = \'%s\', %d", tag2str(nextTag), _stream->pos()); 377 371 378 372 return NULL; 379 373 } 380 374 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 frame414 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 426 375 Codec *AviDecoder::createCodec() { 427 376 switch (_vidsHeader.streamHandler) { 428 377 case ID_CRAM: … … 438 387 return NULL; 439 388 } 440 389 441 Audio::QueuingAudioStream *AviDecoder::createAudioStream() { 390 PixelFormat AviDecoder::getPixelFormat() const { 391 assert(_videoCodec); 392 return _videoCodec->getPixelFormat(); 393 } 442 394 443 if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) { 395 Audio::QueuingAudioStream *AviDecoder::createAudioStream() { 396 if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) 444 397 return Audio::makeQueuingAudioStream(AUDIO_RATE, false); 445 }446 398 447 399 if (_wvInfo.tag != 0) // No sound 448 400 warning ("Unsupported AVI audio format %d", _wvInfo.tag); -
graphics/video/dxa_decoder.h
26 26 #ifndef GRAPHICS_VIDEO_DXA_PLAYER_H 27 27 #define GRAPHICS_VIDEO_DXA_PLAYER_H 28 28 29 #include "graphics/video/video_ player.h"29 #include "graphics/video/video_decoder.h" 30 30 31 31 namespace Graphics { 32 32 … … 38 38 * - sword1 39 39 * - sword2 40 40 */ 41 class DXADecoder : public VideoDecoder {41 class DXADecoder : public FixedRateVideoDecoder { 42 42 public: 43 43 DXADecoder(); 44 44 virtual ~DXADecoder(); 45 45 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; } 51 57 52 58 /** 53 * Close a DXA encoded video file54 */55 void closeFile();56 57 bool decodeNextFrame();58 59 /**60 59 * Get the sound chunk tag of the loaded DXA file 61 60 */ 62 61 uint32 getSoundTag() { return _soundTag; } 63 62 63 protected: 64 double getFrameRate() const { return _frameRate; } 65 66 Common::SeekableReadStream *_fileStream; 67 64 68 private: 65 69 void decodeZlib(byte *data, int size, int totalSize); 66 70 void decode12(int size); … … 72 76 S_DOUBLE 73 77 }; 74 78 79 Graphics::Surface *_surface; 80 byte _palette[256 * 3]; 81 bool _dirtyPalette; 82 75 83 byte *_frameBuffer1; 76 84 byte *_frameBuffer2; 77 85 byte *_scaledBuffer; … … 83 91 uint32 _frameSize; 84 92 ScaleMode _scaleMode; 85 93 uint32 _soundTag; 94 uint16 _width, _height; 95 uint32 _frameRate; 96 uint32 _frameCount; 86 97 }; 87 98 88 99 } // End of namespace Graphics -
graphics/video/flic_decoder.h
23 23 * 24 24 */ 25 25 26 #ifndef GRAPHICS_VIDEO_F licDecoder_H27 #define GRAPHICS_VIDEO_F licDecoder_H26 #ifndef GRAPHICS_VIDEO_FLIC_DECODER_H 27 #define GRAPHICS_VIDEO_FLIC_DECODER_H 28 28 29 #include "graphics/video/video_ player.h"29 #include "graphics/video/video_decoder.h" 30 30 #include "common/list.h" 31 31 #include "common/rect.h" 32 32 … … 42 42 * Video decoder used in engines: 43 43 * - tucker 44 44 */ 45 class FlicDecoder : public VideoDecoder {45 class FlicDecoder : public FixedRateVideoDecoder { 46 46 public: 47 47 FlicDecoder(); 48 48 virtual ~FlicDecoder(); 49 49 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(); 55 52 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(); } 60 59 61 /**62 * Decode the next frame63 */64 bool decodeNextFrame();65 66 60 const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; } 67 61 void clearDirtyRects() { _dirtyRects.clear(); } 68 62 void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); 69 63 70 constbyte *getPalette() { _paletteChanged = false; return _palette; }71 bool paletteChanged() { return _paletteChanged; }64 byte *getPalette() { _paletteChanged = false; return _palette; } 65 bool hasDirtyPalette() { return _paletteChanged; } 72 66 void reset(); 73 67 68 protected: 69 double getFrameRate() const { return _frameRate; } 70 74 71 private: 75 72 uint16 _offsetFrame1; 76 73 uint16 _offsetFrame2; … … 81 78 void decodeDeltaFLC(uint8 *data); 82 79 void unpackPalette(uint8 *mem); 83 80 81 Common::SeekableReadStream *_fileStream; 82 Surface *_surface; 83 uint32 _frameCount; 84 uint32 _frameRate; 85 84 86 Common::List<Common::Rect> _dirtyRects; 85 86 87 }; 87 88 88 89 } // End of namespace Graphics -
graphics/video/avi_decoder.h
26 26 #ifndef GRAPHICS_AVI_PLAYER_H 27 27 #define GRAPHICS_AVI_PLAYER_H 28 28 29 #include "graphics/video/video_ player.h"29 #include "graphics/video/video_decoder.h" 30 30 #include "graphics/video/codecs/codec.h" 31 31 #include "sound/audiostream.h" 32 32 #include "sound/mixer.h" … … 172 172 Common::Rect frame; 173 173 }; 174 174 175 class AviDecoder : public VideoDecoder {175 class AviDecoder : public FixedRateVideoDecoder { 176 176 public: 177 177 AviDecoder(Audio::Mixer *mixer, 178 178 Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); 179 179 virtual ~AviDecoder(); 180 180 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(); 186 183 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; } 191 193 192 bool decodeNextFrame(); 193 int32 getAudioLag(); 194 int32 getFrameRate() { return _vidsHeader.rate / _vidsHeader.scale; } 194 protected: 195 double getFrameRate() const { return (double)_vidsHeader.rate / _vidsHeader.scale; } 195 196 196 197 private: 197 198 Audio::Mixer *_mixer; … … 202 203 AVIStreamHeader _vidsHeader; 203 204 AVIStreamHeader _audsHeader; 204 205 byte _palette[3 * 256]; 206 bool _dirtyPalette; 205 207 208 Common::SeekableReadStream *_stream; 206 209 bool _decodedHeader; 207 210 208 211 Codec *_videoCodec; … … 223 226 static byte char2num(char c); 224 227 static byte getStreamNum(uint32 tag); 225 228 static uint16 getStreamType(uint32 tag); 226 227 Surface *getNextFrame();228 229 }; 229 230 230 231 } // End of namespace Graphics -
graphics/video/codecs/codec.h
28 28 29 29 #include "common/stream.h" 30 30 #include "graphics/surface.h" 31 #include "graphics/pixelformat.h" 31 32 32 33 namespace Graphics { 33 34 … … 35 36 public: 36 37 Codec() {} 37 38 virtual ~Codec() {} 39 38 40 virtual Surface *decodeImage(Common::SeekableReadStream *stream) = 0; 41 virtual PixelFormat getPixelFormat() const = 0; 39 42 }; 40 43 41 44 } // End of namespace Graphics -
graphics/video/codecs/msrle.h
36 36 ~MSRLEDecoder(); 37 37 38 38 Surface *decodeImage(Common::SeekableReadStream *stream); 39 PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); } 39 40 40 41 private: 41 42 byte _bitsPerPixel; -
graphics/video/codecs/msvideo1.cpp
125 125 } 126 126 } 127 127 128 Graphics::Surface *MSVideo1Decoder::decodeImage(Common::SeekableReadStream *stream) {128 Surface *MSVideo1Decoder::decodeImage(Common::SeekableReadStream *stream) { 129 129 if (_bitsPerPixel == 8) 130 130 decode8(stream); 131 131 else { -
graphics/video/codecs/msvideo1.h
36 36 ~MSVideo1Decoder(); 37 37 38 38 Surface *decodeImage(Common::SeekableReadStream *stream); 39 PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); } 39 40 40 41 private: 41 42 byte _bitsPerPixel; -
graphics/video/smk_decoder.cpp
351 351 352 352 SmackerDecoder::SmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) 353 353 : _audioStarted(false), _audioStream(0), _mixer(mixer), _soundType(soundType) { 354 _surface = 0; 355 _fileStream = 0; 356 _dirtyPalette = false; 354 357 } 355 358 356 359 SmackerDecoder::~SmackerDecoder() { 357 close File();360 close(); 358 361 } 359 362 360 int SmackerDecoder::getHeight() { 361 if (!_fileStream) 362 return 0; 363 return (_header.flags ? 2 : 1) * _videoInfo.height; 364 } 363 uint32 SmackerDecoder::getElapsedTime() const { 364 if (_audioStream) 365 return _mixer->getSoundElapsedTime(_audioHandle); 365 366 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(); 387 368 } 388 369 389 bool SmackerDecoder::load File(const char *fileName) {390 int32 frameRate;370 bool SmackerDecoder::load(Common::SeekableReadStream &stream) { 371 close(); 391 372 392 closeFile();373 _fileStream = &stream; 393 374 394 _fileStream = SearchMan.createReadStreamForMember(fileName);395 if (!_fileStream)396 return false;397 398 375 // Seek to the first frame 399 _videoInfo.currentFrame = 0;400 376 _header.signature = _fileStream->readUint32BE(); 401 377 402 378 // No BINK support available … … 408 384 409 385 assert(_header.signature == MKID_BE('SMK2') || _header.signature == MKID_BE('SMK4')); 410 386 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(); 415 391 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; 426 398 427 399 // Flags are determined by which bit is set, which can be one of the following: 428 400 // 0 - set to 1 if file contains a ring frame. … … 447 419 _header.fullSize = _fileStream->readUint32LE(); 448 420 _header.typeSize = _fileStream->readUint32LE(); 449 421 450 uint32 audioInfo;451 422 for (i = 0; i < 7; ++i) { 452 423 // AudioRate - Frequency and format information for each sound track, up to 7 audio tracks. 453 424 // The 32 constituent bits have the following meaning: … … 458 429 // * bits 27-26 - if both set to zero - use v2 sound decompression 459 430 // * bits 25-24 - unused 460 431 // * bits 23-0 - audio sample rate 461 audioInfo = _fileStream->readUint32LE();432 uint32 audioInfo = _fileStream->readUint32LE(); 462 433 _header.audioInfo[i].isCompressed = audioInfo & 0x80000000; 463 434 _header.audioInfo[i].hasAudio = audioInfo & 0x40000000; 464 435 _header.audioInfo[i].is16Bits = audioInfo & 0x20000000; … … 467 438 !(audioInfo & 0x4000000); 468 439 _header.audioInfo[i].sampleRate = audioInfo & 0xFFFFFF; 469 440 470 if (_header.audioInfo[i].hasAudio && i == 0) {441 if (_header.audioInfo[i].hasAudio && i == 0) 471 442 _audioStream = Audio::makeQueuingAudioStream(_header.audioInfo[0].sampleRate, _header.audioInfo[0].isStereo); 472 }473 443 } 474 444 475 445 _header.dummy = _fileStream->readUint32LE(); 476 446 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) 479 449 _frameSizes[i] = _fileStream->readUint32LE(); 480 450 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) 483 453 _frameTypes[i] = _fileStream->readByte(); 484 454 485 455 byte *huffmanTrees = new byte[_header.treesSize]; … … 494 464 495 465 delete[] huffmanTrees; 496 466 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); 499 469 _palette = (byte *)malloc(3 * 256); 500 470 memset(_palette, 0, 3 * 256); 501 502 _videoInfo.firstframeOffset = _fileStream->pos();503 504 471 return true; 505 472 } 506 473 507 void SmackerDecoder::close File() {474 void SmackerDecoder::close() { 508 475 if (!_fileStream) 509 476 return; 510 477 … … 517 484 delete _fileStream; 518 485 _fileStream = 0; 519 486 487 _surface->free(); 488 delete _surface; 489 _surface = 0; 490 520 491 delete _MMapTree; 521 492 delete _MClrTree; 522 493 delete _FullTree; 523 494 delete _TypeTree; 524 495 525 free(_frameSizes); 526 free(_frameTypes); 527 free(_videoFrameBuffer); 496 delete[] _frameSizes; 497 delete[] _frameTypes; 528 498 free(_palette); 499 500 reset(); 529 501 } 530 502 531 boolSmackerDecoder::decodeNextFrame() {503 Surface *SmackerDecoder::decodeNextFrame() { 532 504 uint i; 533 505 uint32 chunkSize = 0; 534 506 uint32 dataSizeUnpacked = 0; 535 507 536 508 uint32 startPos = _fileStream->pos(); 537 509 538 if (_videoInfo.currentFrame == 0) 539 _videoInfo.startTime = g_system->getMillis(); 510 _curFrame++; 540 511 541 512 // Check if we got a frame with palette data, and 542 513 // call back the virtual setPalette function to set 543 514 // the current palette 544 if (_frameTypes[_ videoInfo.currentFrame] & 1) {515 if (_frameTypes[_curFrame] & 1) { 545 516 unpackPalette(); 546 setPalette(_palette);517 _dirtyPalette = true; 547 518 } 548 519 549 520 // Load audio tracks 550 521 for (i = 0; i < 7; ++i) { 551 if (!(_frameTypes[_ videoInfo.currentFrame] & (2 << i)))522 if (!(_frameTypes[_curFrame] & (2 << i))) 552 523 continue; 553 524 554 525 chunkSize = _fileStream->readUint32LE(); … … 596 567 } 597 568 } 598 569 599 uint32 frameSize = _frameSizes[_ videoInfo.currentFrame] & ~3;570 uint32 frameSize = _frameSizes[_curFrame] & ~3; 600 571 601 572 if (_fileStream->pos() - startPos > frameSize) 602 e xit(1);573 error("Smacker actual frame size exceeds recorded frame size"); 603 574 604 575 uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos); 605 576 … … 613 584 _FullTree->reset(); 614 585 _TypeTree->reset(); 615 586 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(); 619 590 uint block = 0, blocks = bw*bh; 620 591 621 592 uint doubleY = _header.flags ? 2 : 1; … … 634 605 while (run-- && block < blocks) { 635 606 clr = _MClrTree->getCode(bs); 636 607 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; 638 609 hi = clr >> 8; 639 610 lo = clr & 0xff; 640 611 for (i = 0; i < 4; i++) { … … 667 638 } 668 639 669 640 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; 671 642 switch (mode) { 672 643 case 0: 673 644 for (i = 0; i < 4; ++i) { … … 733 704 uint32 col; 734 705 mode = type >> 8; 735 706 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; 737 708 col = mode * 0x01010101; 738 709 for (i = 0; i < 4 * doubleY; ++i) { 739 710 out[0] = out[1] = out[2] = out[3] = col; … … 749 720 750 721 free(_frameData); 751 722 752 return ++_videoInfo.currentFrame < _videoInfo.frameCount; 723 if (_curFrame == 0) 724 _startTime = g_system->getMillis(); 725 726 return _surface; 753 727 } 754 728 755 729 void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, … … 804 778 // If the sample is stereo, the data is stored for the left and right channel, respectively 805 779 // (the exact opposite to the base values) 806 780 if (!is16Bits) { 807 808 781 for (int k = 0; k < (isStereo ? 2 : 1); k++) { 809 782 bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS)); 810 783 *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80; 811 784 curPos++; 812 785 } 813 814 786 } else { 815 816 787 for (int k = 0; k < (isStereo ? 2 : 1); k++) { 817 788 bases[k] += (int16) (audioTrees[k * 2]->getCode(audioBS) | 818 789 (audioTrees[k * 2 + 1]->getCode(audioBS) << 8)); … … 885 856 } 886 857 887 858 _fileStream->seek(startPos + len); 888 889 859 free(chunk); 890 860 } 891 861 -
graphics/video/video_player.cpp
1 /* ScummVM - Graphic Adventure Engine2 *3 * ScummVM is the legal property of its developers, whose names4 * are too numerous to list here. Please refer to the COPYRIGHT5 * file distributed with this source distribution.6 *7 * This program is free software; you can redistribute it and/or8 * modify it under the terms of the GNU General Public License9 * as published by the Free Software Foundation; either version 210 * 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 of14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15 * GNU General Public License for more details.16 17 * You should have received a copy of the GNU General Public License18 * along with this program; if not, write to the Free Software19 * 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 frame89 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 palette135 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 * VideoPlayer158 */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 pressed165 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 screen214 g_system->updateScreen();215 216 startTime = g_system->getMillis();217 218 // Wait before showing the next frame219 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
26 26 #ifndef GRAPHICS_VIDEO_SMK_PLAYER_H 27 27 #define GRAPHICS_VIDEO_SMK_PLAYER_H 28 28 29 #include "graphics/video/video_ player.h"29 #include "graphics/video/video_decoder.h" 30 30 #include "sound/mixer.h" 31 31 32 32 namespace Audio { … … 51 51 * - sword1 52 52 * - sword2 53 53 */ 54 class SmackerDecoder : public VideoDecoder {54 class SmackerDecoder : public FixedRateVideoDecoder { 55 55 public: 56 56 SmackerDecoder(Audio::Mixer *mixer, 57 57 Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType); 58 58 virtual ~SmackerDecoder(); 59 59 60 int getHeight();61 int32 getAudioLag();60 bool load(Common::SeekableReadStream &stream); 61 void close(); 62 62 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; } 68 72 69 /** 70 * Close an SMK encoded video file 71 */ 72 void closeFile(); 73 protected: 74 double getFrameRate() const { return _frameRate; } 75 Common::SeekableReadStream *_fileStream; 73 76 74 bool decodeNextFrame();75 76 77 private: 77 78 void unpackPalette(); 78 79 // Possible runs of blocks … … 111 112 byte *_frameData; 112 113 // The RGB palette 113 114 byte *_palette; 115 bool _dirtyPalette; 114 116 117 uint32 _frameRate; 118 uint32 _frameCount; 119 Surface *_surface; 120 115 121 Audio::Mixer::SoundType _soundType; 116 122 Audio::Mixer *_mixer; 117 123 bool _audioStarted; -
graphics/video/video_player.h
1 /* ScummVM - Graphic Adventure Engine2 *3 * ScummVM is the legal property of its developers, whose names4 * are too numerous to list here. Please refer to the COPYRIGHT5 * file distributed with this source distribution.6 *7 * This program is free software; you can redistribute it and/or8 * modify it under the terms of the GNU General Public License9 * as published by the Free Software Foundation; either version 210 * 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 of14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15 * GNU General Public License for more details.16 17 * You should have received a copy of the GNU General Public License18 * along with this program; if not, write to the Free Software19 * 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_H27 #define GRAPHICS_VIDEO_PLAYER_H28 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 decoder41 */42 class VideoDecoder {43 public:44 VideoDecoder();45 virtual ~VideoDecoder();46 47 /**48 * Returns the width of the video49 * @return the width of the video50 */51 virtual int getWidth();52 53 /**54 * Returns the height of the video55 * @return the height of the video56 */57 virtual int getHeight();58 59 /**60 * Returns the current frame number of the video61 * @return the current frame number of the video62 */63 virtual int32 getCurFrame();64 65 /**66 * Returns the amount of frames in the video67 * @return the amount of frames in the video68 */69 virtual int32 getFrameCount();70 71 /**72 * Returns the frame rate of the video73 * @return the frame rate of the video74 */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 behind86 * If < 0, video lags behind87 * @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 lag93 * @return the time to wait until the next frame in ms94 */95 virtual uint32 getFrameWaitTime();96 97 /**98 * Load a video file99 * @param filename the filename to load100 */101 virtual bool loadFile(const char *filename) = 0;102 103 /**104 * Close a video file105 */106 virtual void closeFile() = 0;107 108 /**109 * Returns if a video file is loaded or not110 */111 bool isVideoLoaded() { return (_fileStream != NULL); }112 113 /**114 * Set RGB palette, based on current frame115 * @param pal the RGB palette data116 */117 virtual void setPalette(byte *pal);118 119 /**120 * Gets the value of the pixel at the specified x and y coordinates121 * Note: This method assumes that the video's pitch equals its width, and that122 * the video has an 8bpp palette123 * @param x the x coordinate of the pixel124 * @param y the y coordinate of the pixel125 */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 offset132 * @param offset the offset of the pixel in the video buffer133 */134 byte getPixel(int offset) { return getPixel(offset, 0); }135 136 /**137 * Return the black palette color for the current frame138 */139 byte getBlack() { return _curFrameBlack; }140 141 /**142 * Return the white palette color for the current frame143 */144 byte getWhite() { return _curFrameWhite; }145 146 /**147 * Copy current frame into the specified position of the destination148 * buffer.149 * @param dst the buffer150 * @param x the x position of the buffer151 * @param y the y position of the buffer152 * @param pitch the pitch of buffer153 */154 void copyFrameToBuffer(byte *dst, uint x, uint y, uint pitch);155 156 /**157 * Decode the next frame to _videoFrameBuffer158 */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 player186 * Plays a non-interactive full screen video till it's stopped by a187 * specific event188 * @param filename the name of the file to play189 * @param stopEvents a list of events that can stop the video190 *191 * Returns true if the video was played to the end, false if skipped192 */193 bool playVideo(Common::List<Common::Event> &stopEvents);194 195 /**196 * Provides the same functionality as the video player, and it adds the197 * event of skipping the video with the escape key by default198 */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 Graphics215 216 #endif -
graphics/video/video_decoder.cpp
23 23 * 24 24 */ 25 25 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" 29 29 #include "common/system.h" 30 #include "common/util.h"31 #include "common/array.h"32 #include "common/endian.h"33 30 34 #include "graphics/video/video_player.h"35 #include "graphics/surface.h"36 37 31 namespace Graphics { 38 32 39 VideoDecoder::VideoDecoder() : _fileStream(0) { 40 _curFrameBlack = 0; 41 _curFrameWhite = 255; 33 VideoDecoder::VideoDecoder() { 34 reset(); 42 35 } 43 36 44 VideoDecoder::~VideoDecoder() {45 } 37 bool VideoDecoder::loadFile(const Common::String &filename) { 38 Common::File *file = new Common::File(); 46 39 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 } 52 44 53 int VideoDecoder::getHeight() { 54 if (!_fileStream) 55 return 0; 56 return _videoInfo.height; 45 return load(*file); 57 46 } 58 47 59 int32 VideoDecoder::getCurFrame() { 60 if (!_fileStream) 61 return -1; 62 return _videoInfo.currentFrame; 48 uint32 VideoDecoder::getElapsedTime() const { 49 return g_system->getMillis() - _startTime; 63 50 } 64 51 65 int32 VideoDecoder::getFrameCount() { 66 if (!_fileStream) 67 return 0; 68 return _videoInfo.frameCount; 69 } 52 void VideoDecoder::setSystemPalette() { 53 byte *vidPalette = getPalette(); 54 byte *sysPalette = new byte[256 * 4]; 70 55 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 } 76 62 77 int32 VideoDecoder::getFrameDelay() { 78 if (!_fileStream) 79 return 0; 80 return _videoInfo.frameDelay; 63 g_system->setPalette(sysPalette, 0, 256); 64 delete[] sysPalette; 81 65 } 82 66 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; 67 bool VideoDecoder::needsUpdate() const { 68 return !endOfVideo() && getTimeToNextFrame() == 0; 95 69 } 96 70 97 uint32 VideoDecoder::getFrameWaitTime() { 98 int32 waitTime = (getFrameDelay() + getAudioLag()) / 100; 99 100 if (waitTime < 0) 101 return 0; 102 103 return waitTime; 71 void VideoDecoder::reset() { 72 _curFrame = -1; 73 _startTime = 0; 104 74 } 105 75 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); 76 bool VideoDecoder::endOfVideo() const { 77 return !isVideoLoaded() || getCurFrame() >= (int32)getFrameCount() - 1; 118 78 } 119 79 120 void VideoDecoder::setPalette(byte *pal) { 121 byte videoPalette[256 * 4]; 80 uint32 FixedRateVideoDecoder::getTimeToNextFrame() const { 81 if (endOfVideo() || _curFrame < 0) 82 return 0; 122 83 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); 127 86 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; 133 91 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; 153 93 } 154 94 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 } 95 uint32 FixedRateVideoDecoder::getFrameBeginTime(uint32 frame) const { 96 return (uint32)(frame * 1000 / getFrameRate()); 184 97 } 185 98 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 screen214 g_system->updateScreen();215 216 startTime = g_system->getMillis();217 218 // Wait before showing the next frame219 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 99 } // End of namespace Graphics