Ticket #9141: vid_dec_graphics.diff
| File vid_dec_graphics.diff, 52.7 KB (added by , 16 years ago) |
|---|
-
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
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/graphics/video/video_decoder.h $ 22 * $Id$ 23 * 24 */ 25 26 #ifndef GRAPHICS_VIDEO_PLAYER_H 27 #define GRAPHICS_VIDEO_PLAYER_H 28 29 #include "common/events.h" 30 #include "common/list.h" 31 #include "common/rational.h" 32 #include "common/stream.h" 33 34 #include "graphics/surface.h" 35 #include "graphics/pixelformat.h" 36 37 namespace Common { 38 class SeekableReadStream; 39 } 40 41 namespace Graphics { 42 43 /** 44 * Implementation of a generic video decoder 45 */ 46 class VideoDecoder { 47 public: 48 VideoDecoder(); 49 virtual ~VideoDecoder() {} 50 51 /** 52 * Returns the width of the video 53 * @return the width of the video 54 */ 55 virtual uint16 getWidth() const = 0; 56 57 /** 58 * Returns the height of the video 59 * @return the height of the video 60 */ 61 virtual uint16 getHeight() const = 0; 62 63 /** 64 * Returns the current frame number of the video 65 * @return the last frame decoded by the video 66 */ 67 virtual int32 getCurFrame() const { return _curFrame; } 68 69 /** 70 * Returns the amount of frames in the video 71 * @return the amount of frames in the video 72 */ 73 virtual uint32 getFrameCount() const = 0; 74 75 /** 76 * Returns the time (in ms) that the video has been running 77 */ 78 virtual uint32 getElapsedTime() const; 79 80 /** 81 * Returns whether a frame should be decoded or not 82 * @return whether a frame should be decoded or not 83 */ 84 virtual bool needsUpdate() const; 85 86 /** 87 * Load a video file 88 * @param filename the filename to load 89 */ 90 virtual bool loadFile(const Common::String &filename); 91 92 /** 93 * Load a video file 94 * @param stream the stream to load 95 */ 96 virtual bool load(Common::SeekableReadStream &stream) = 0; 97 98 /** 99 * Close a video file 100 */ 101 virtual void close() = 0; 102 103 /** 104 * Returns if a video file is loaded or not 105 */ 106 virtual bool isVideoLoaded() const = 0; 107 108 /** 109 * Decode the next frame and return the frame's surface 110 * @note the return surface should *not* be freed 111 * @note this may return 0, in which case the last frame should be kept on screen 112 */ 113 virtual Surface *decodeNextFrame() = 0; 114 115 /** 116 * Get the pixel format of the video 117 */ 118 virtual PixelFormat getPixelFormat() const = 0; 119 120 /** 121 * Get the palette for the video in RGB format (if 8bpp or less) 122 */ 123 virtual byte *getPalette() { return 0; } 124 125 /** 126 * Returns if the palette is dirty or not 127 */ 128 virtual bool hasDirtyPalette() const { return false; } 129 130 /** 131 * Add the time the video has been paused to maintain sync 132 */ 133 virtual void addPauseTime(uint32 ms) { _startTime += ms; } 134 135 /** 136 * Returns if the video is finished or not 137 */ 138 virtual bool endOfVideo() const; 139 140 /** 141 * Set the current palette to the system palette 142 */ 143 void setSystemPalette(); 144 145 /** 146 * Return the time until the next frame (in ms) 147 */ 148 virtual uint32 getTimeToNextFrame() const = 0; 149 150 protected: 151 /** 152 * Resets _curFrame and _startTime. Should be called from every close() function. 153 */ 154 void reset(); 155 156 int32 _curFrame; 157 uint32 _startTime; 158 }; 159 160 /** 161 * A VideoDecoder wrapper that implements getTimeToNextFrame() based on getFrameRate(). 162 */ 163 class FixedRateVideoDecoder : public VideoDecoder { 164 public: 165 FixedRateVideoDecoder() {} 166 virtual ~FixedRateVideoDecoder() {} 167 168 uint32 getTimeToNextFrame() const; 169 170 protected: 171 /** 172 * Return the frame rate in frames per second 173 * This returns a Rational because videos can have rates that are not integers and 174 * there are some videos with frame rates < 1. 175 */ 176 virtual Common::Rational getFrameRate() const = 0; 177 178 private: 179 uint32 getFrameBeginTime(uint32 frame) const; 180 }; 181 182 } // End of namespace Graphics 183 184 #endif -
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 = -1; 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(), getFrameRate().toInt()); 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 = -1;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 _videoInfo.currentFrame++; 488 489 if (_videoInfo.currentFrame == 0) 490 _videoInfo.startTime = g_system->getMillis(); 491 492 tag = _fileStream->readUint32BE(); 479 Surface *DXADecoder::decodeNextFrame() { 480 uint32 tag = _fileStream->readUint32BE(); 493 481 if (tag == MKID_BE('CMAP')) { 494 byte rgb[768]; 495 496 _fileStream->read(rgb, ARRAYSIZE(rgb)); 497 setPalette(rgb); 482 _fileStream->read(_palette, 256 * 3); 483 _dirtyPalette = true; 498 484 } 499 485 500 486 tag = _fileStream->readUint32BE(); … … 531 517 532 518 if (type == 3) { 533 519 for (uint32 j = 0; j < _curHeight; ++j) { 534 for (uint32 i = 0; i < _ videoInfo.width; ++i) {535 const int offs = j * _ videoInfo.width + i;520 for (uint32 i = 0; i < _width; ++i) { 521 const int offs = j * _width + i; 536 522 _frameBuffer1[offs] ^= _frameBuffer2[offs]; 537 523 } 538 524 } … … 542 528 switch (_scaleMode) { 543 529 case S_INTERLACED: 544 530 for (int cy = 0; cy < _curHeight; cy++) { 545 memcpy(&_scaledBuffer[2 * cy * _ videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);546 memset(&_scaledBuffer[((2 * cy) + 1) * _ videoInfo.width], 0, _videoInfo.width);531 memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width); 532 memset(&_scaledBuffer[((2 * cy) + 1) * _width], 0, _width); 547 533 } 548 _ videoFrameBuffer= _scaledBuffer;534 _surface->pixels = _scaledBuffer; 549 535 break; 550 536 case S_DOUBLE: 551 537 for (int cy = 0; cy < _curHeight; cy++) { 552 memcpy(&_scaledBuffer[2 * cy * _ videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);553 memcpy(&_scaledBuffer[((2 * cy) + 1) * _ videoInfo.width], &_frameBuffer1[cy * _videoInfo.width], _videoInfo.width);538 memcpy(&_scaledBuffer[2 * cy * _width], &_frameBuffer1[cy * _width], _width); 539 memcpy(&_scaledBuffer[((2 * cy) + 1) * _width], &_frameBuffer1[cy * _width], _width); 554 540 } 555 _ videoFrameBuffer= _scaledBuffer;541 _surface->pixels = _scaledBuffer; 556 542 break; 557 543 case S_NONE: 558 _ videoFrameBuffer= _frameBuffer1;544 _surface->pixels = _frameBuffer1; 559 545 break; 560 546 } 561 547 562 return !endOfVideo(); 548 // Copy in the relevant info to the Surface 549 _surface->w = getWidth(); 550 _surface->h = getHeight(); 551 _surface->pitch = getWidth(); 552 553 _curFrame++; 554 555 if (_curFrame == 0) 556 _startTime = g_system->getMillis(); 557 558 return _surface; 563 559 } 564 560 565 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 = -1;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 boolFlicDecoder::decodeNextFrame() {198 Surface *FlicDecoder::decodeNextFrame() { 198 199 // Read chunk 199 200 uint32 frameSize = _fileStream->readUint32LE(); 200 201 uint16 frameType = _fileStream->readUint16LE(); 201 202 uint16 chunkCount = 0; 202 203 203 204 switch (frameType) { 204 case FRAME_TYPE: { 205 chunkCount = _fileStream->readUint16LE(); 206 // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword) 207 // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here 208 uint16 newFrameDelay = _fileStream->readUint16LE(); // "speed", in milliseconds 209 if (newFrameDelay > 0) { 210 _videoInfo.frameDelay = 100 * newFrameDelay; 211 _videoInfo.frameRate = 100 * 1000 / _videoInfo.frameDelay; 212 } 213 _fileStream->readUint16LE(); // reserved, always 0 214 uint16 newWidth = _fileStream->readUint16LE(); 215 uint16 newHeight = _fileStream->readUint16LE(); 216 if (newWidth > 0) 217 _videoInfo.width = newWidth; 218 if (newHeight > 0) 219 _videoInfo.height = newHeight; 205 case FRAME_TYPE: 206 { 207 // FIXME: FLIC should be switched over to a variable frame rate VideoDecoder to handle 208 // this properly. 220 209 221 _videoInfo.currentFrame++; 210 chunkCount = _fileStream->readUint16LE(); 211 // Note: The overriden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword) 212 // frameDelay is the FLIC "speed", in milliseconds. Our frameDelay is calculated in 1/100 ms, so we convert it here 213 uint16 newFrameDelay = _fileStream->readUint16LE(); // "speed", in milliseconds 214 if (newFrameDelay > 0) 215 _frameRate = 1000 / newFrameDelay; 222 216 223 if (_videoInfo.currentFrame == 0) 224 _videoInfo.startTime = g_system->getMillis(); 217 _fileStream->readUint16LE(); // reserved, always 0 218 uint16 newWidth = _fileStream->readUint16LE(); 219 uint16 newHeight = _fileStream->readUint16LE(); 220 221 if ((newWidth != 0) && (newHeight != 0)) { 222 if (newWidth == 0) 223 newWidth = _surface->w; 224 if (newHeight == 0) 225 newHeight = _surface->h; 226 227 _surface->free(); 228 delete _surface; 229 _surface = new Graphics::Surface(); 230 _surface->create(newWidth, newHeight, 1); 231 } 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 == (int32)_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 !endOfVideo();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" … … 49 48 _audStream = NULL; 50 49 _fileStream = NULL; 51 50 _audHandle = new Audio::SoundHandle(); 51 _dirtyPalette = false; 52 52 memset(_palette, 0, sizeof(_palette)); 53 53 memset(&_wvInfo, 0, sizeof(PCMWAVEFORMAT)); 54 54 memset(&_bmInfo, 0, sizeof(BITMAPINFOHEADER)); … … 58 58 } 59 59 60 60 AviDecoder::~AviDecoder() { 61 close File();61 close(); 62 62 delete _audHandle; 63 63 } 64 64 … … 190 190 /*_palette[i * 4 + 3] = */_fileStream->readByte(); 191 191 } 192 192 193 setPalette(_palette);193 _dirtyPalette = true; 194 194 } 195 195 } else if (sHeader.streamType == ID_AUDS) { 196 196 _audsHeader = sHeader; … … 204 204 } 205 205 } 206 206 207 bool AviDecoder::load File(const char *fileName) {208 close File();207 bool AviDecoder::load(Common::SeekableReadStream &stream) { 208 close(); 209 209 210 _fileStream = SearchMan.createReadStreamForMember(fileName); 211 if (!_fileStream) 212 return false; 213 210 _fileStream = &stream; 214 211 _decodedHeader = false; 215 // Seek to the first frame216 _videoInfo.currentFrame = -1;217 212 218 213 // Read chunks until we have decoded the header 219 214 while (!_decodedHeader) 220 215 runHandle(_fileStream->readUint32BE()); 221 216 222 _videoFrameBuffer = new byte[_header.width * _header.height];223 memset(_videoFrameBuffer, 0, _header.width * _header.height);224 225 217 uint32 nextTag = _fileStream->readUint32BE(); 226 218 227 219 // Throw out any JUNK section … … 247 239 _mixer->playStream(_soundType, _audHandle, _audStream); 248 240 249 241 debug (0, "Frames = %d, Dimensions = %d x %d", _header.totalFrames, _header.width, _header.height); 250 debug (0, "Frame Rate = %d", getFrameRate());242 debug (0, "Frame Rate = %d", _vidsHeader.rate / _vidsHeader.scale); 251 243 if ((_audsHeader.scale != 0) && (_header.flags & AVIF_ISINTERLEAVED)) 252 244 debug (0, "Sound Rate = %d", AUDIO_RATE); 253 245 debug (0, "Video Codec = \'%s\'", tag2str(_vidsHeader.streamHandler)); 254 246 255 _videoInfo.firstframeOffset = _fileStream->pos();256 _videoInfo.width = _header.width;257 _videoInfo.height = _header.height;258 _videoInfo.frameCount = _header.totalFrames;259 // Our frameDelay is calculated in 1/100 ms, so we convert it here260 _videoInfo.frameDelay = _header.microSecondsPerFrame / 10;261 262 247 if (!_videoCodec) 263 248 return false; 264 249 265 250 return true; 266 251 } 267 252 268 void AviDecoder::close File() {253 void AviDecoder::close() { 269 254 if (!_fileStream) 270 255 return; 271 256 272 257 delete _fileStream; 273 258 _fileStream = 0; 274 259 275 delete[] _videoFrameBuffer;276 _videoFrameBuffer = 0;277 278 260 // Deinitialize sound 279 261 _mixer->stopHandle(*_audHandle); 280 262 _audStream = 0; … … 293 275 memset(&_vidsHeader, 0, sizeof(AVIStreamHeader)); 294 276 memset(&_audsHeader, 0, sizeof(AVIStreamHeader)); 295 277 memset(&_ixInfo, 0, sizeof(AVIOLDINDEX)); 278 279 reset(); 296 280 } 297 281 298 Surface *AviDecoder::getNextFrame() { 282 uint32 AviDecoder::getElapsedTime() const { 283 if (_audStream) 284 return _mixer->getSoundElapsedTime(*_audHandle); 285 286 return VideoDecoder::getElapsedTime(); 287 } 288 289 Surface *AviDecoder::decodeNextFrame() { 299 290 uint32 nextTag = _fileStream->readUint32BE(); 300 291 301 292 if (_fileStream->eos()) 302 293 return NULL; 303 294 295 if (_curFrame == -1) 296 _startTime = g_system->getMillis(); 297 304 298 if (nextTag == ID_LIST) { 305 299 // A list of audio/video chunks 306 300 uint32 listSize = _fileStream->readUint32LE() - 4; … … 312 306 // Decode chunks in the list and see if we get a frame 313 307 Surface *frame = NULL; 314 308 while (_fileStream->pos() < startPos + (int32)listSize) { 315 Surface *temp = getNextFrame();309 Surface *temp = decodeNextFrame(); 316 310 if (temp) 317 311 frame = temp; 318 312 } … … 335 329 } else if (getStreamType(nextTag) == 'dc' || getStreamType(nextTag) == 'id' || 336 330 getStreamType(nextTag) == 'AM' || getStreamType(nextTag) == '32') { 337 331 // Compressed Frame 338 _ videoInfo.currentFrame++;332 _curFrame++; 339 333 uint32 chunkSize = _fileStream->readUint32LE(); 340 334 341 335 if (chunkSize == 0) // Keep last frame on screen … … 364 358 _fileStream->readByte(); // Flags that don't serve us any purpose 365 359 } 366 360 367 setPalette(_palette);361 _dirtyPalette = true; 368 362 369 363 // No alignment necessary. It's always even. 370 364 } else if (nextTag == ID_JUNK) { … … 372 366 } else if (nextTag == ID_IDX1) { 373 367 runHandle(ID_IDX1); 374 368 } else 375 error ("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos());369 error("Tag = \'%s\', %d", tag2str(nextTag), _fileStream->pos()); 376 370 377 371 return NULL; 378 372 } 379 373 380 bool AviDecoder::decodeNextFrame() {381 Surface *surface = NULL;382 383 int32 curFrame = _videoInfo.currentFrame;384 385 while (!surface && !endOfVideo() && !_fileStream->eos())386 surface = getNextFrame();387 388 if (curFrame == _videoInfo.currentFrame) {389 warning("No video frame found");390 _videoInfo.currentFrame++;391 }392 393 if (surface)394 memcpy(_videoFrameBuffer, surface->pixels, _header.width * _header.height);395 396 if (_videoInfo.currentFrame == 0)397 _videoInfo.startTime = g_system->getMillis();398 399 return !endOfVideo();400 }401 402 int32 AviDecoder::getAudioLag() {403 if (!_fileStream)404 return 0;405 406 int32 frameDelay = getFrameDelay();407 int32 videoTime = (_videoInfo.currentFrame + 1) * frameDelay;408 int32 audioTime;409 410 if (!_audStream) {411 /* No audio.412 Calculate the lag by how much time has gone by since the first frame413 and how much time *should* have passed.414 */415 416 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100;417 } else {418 const Audio::Timestamp ts = _mixer->getElapsedTime(*_audHandle);419 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames();420 }421 422 return videoTime - audioTime;423 }424 425 374 Codec *AviDecoder::createCodec() { 426 375 switch (_vidsHeader.streamHandler) { 427 376 case ID_CRAM: … … 437 386 return NULL; 438 387 } 439 388 440 Audio::QueuingAudioStream *AviDecoder::createAudioStream() { 389 PixelFormat AviDecoder::getPixelFormat() const { 390 assert(_videoCodec); 391 return _videoCodec->getPixelFormat(); 392 } 441 393 442 if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) { 394 Audio::QueuingAudioStream *AviDecoder::createAudioStream() { 395 if (_wvInfo.tag == AVI_WAVE_FORMAT_PCM) 443 396 return Audio::makeQueuingAudioStream(AUDIO_RATE, false); 444 }445 397 446 398 if (_wvInfo.tag != 0) // No sound 447 399 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 Common::Rational 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_FLICDECODER_H 27 #define GRAPHICS_VIDEO_FLICDECODER_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 50 /** 51 * Load a FLIC encodedvideo file52 * @param filename the filenameto load51 * Load a video file 52 * @param stream the stream to load 53 53 */ 54 bool loadFile(const char *fileName); 54 bool load(Common::SeekableReadStream &stream); 55 void close(); 55 56 56 57 /** 57 * Close a FLIC encoded video file 58 * Decode the next frame and return the frame's surface 59 * @note the return surface should *not* be freed 60 * @note this may return 0, in which case the last frame should be kept on screen 58 61 */ 59 void closeFile();62 Surface *decodeNextFrame(); 60 63 61 /** 62 * Decode the next frame 63 */ 64 bool decodeNextFrame(); 64 bool isVideoLoaded() const { return _fileStream != 0; } 65 uint16 getWidth() const { return _surface->w; } 66 uint16 getHeight() const { return _surface->h; } 67 uint32 getFrameCount() const { return _frameCount; } 68 PixelFormat getPixelFormat() const { return PixelFormat::createFormatCLUT8(); } 65 69 66 70 const Common::List<Common::Rect> *getDirtyRects() const { return &_dirtyRects; } 67 71 void clearDirtyRects() { _dirtyRects.clear(); } 68 72 void copyDirtyRectsToBuffer(uint8 *dst, uint pitch); 69 73 70 constbyte *getPalette() { _paletteChanged = false; return _palette; }71 bool paletteChanged() { return _paletteChanged; }74 byte *getPalette() { _paletteChanged = false; return _palette; } 75 bool hasDirtyPalette() { return _paletteChanged; } 72 76 void reset(); 73 77 78 protected: 79 Common::Rational getFrameRate() const { return _frameRate; } 80 74 81 private: 75 82 uint16 _offsetFrame1; 76 83 uint16 _offsetFrame2; … … 81 88 void decodeDeltaFLC(uint8 *data); 82 89 void unpackPalette(uint8 *mem); 83 90 91 Common::SeekableReadStream *_fileStream; 92 Surface *_surface; 93 uint32 _frameCount; 94 uint32 _frameRate; 95 84 96 Common::List<Common::Rect> _dirtyRects; 85 86 97 }; 87 98 88 99 } // 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 _fileStream != 0; } 185 uint16 getWidth() const { return _header.width; } 186 uint16 getHeight() const { return _header.height; } 187 uint32 getFrameCount() const { return _header.totalFrames; } 188 uint32 getElapsedTime() const; 189 Surface *decodeNextFrame(); 190 PixelFormat getPixelFormat() const; 191 byte *getPalette() { _dirtyPalette = false; return _palette; } 192 bool hasDirtyPalette() const { return _dirtyPalette; } 191 193 192 bool decodeNextFrame(); 193 int32 getAudioLag(); 194 int32 getFrameRate() { return _vidsHeader.rate / _vidsHeader.scale; } 194 protected: 195 Common::Rational getFrameRate() const { return Common::Rational(_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 *_fileStream; 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 + 1) * frameDelay; 372 int32 audioTime; 373 374 if (!_audioStream) { 375 /* No audio. 376 Calculate the lag by how much time has gone by since the first frame 377 and how much time *should* have passed. 378 */ 379 380 audioTime = (g_system->getMillis() - _videoInfo.startTime) * 100; 381 } else { 382 const Audio::Timestamp ts = _mixer->getElapsedTime(_audioHandle); 383 audioTime = ts.convertToFramerate(100000).totalNumberOfFrames(); 384 } 385 386 return videoTime - audioTime; 367 return VideoDecoder::getElapsedTime(); 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 = -1;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); 499 _palette = (byte *)malloc(3 * 256); 500 memset(_palette, 0, 3 * 256); 467 _surface = new Graphics::Surface(); 501 468 502 _videoInfo.firstframeOffset = _fileStream->pos(); 469 // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled) 470 _surface->create(width, height * (_header.flags ? 2 : 1), 1); 503 471 472 _palette = (byte *)malloc(3 * 256); 473 memset(_palette, 0, 3 * 256); 504 474 return true; 505 475 } 506 476 507 void SmackerDecoder::close File() {477 void SmackerDecoder::close() { 508 478 if (!_fileStream) 509 479 return; 510 480 … … 517 487 delete _fileStream; 518 488 _fileStream = 0; 519 489 490 _surface->free(); 491 delete _surface; 492 _surface = 0; 493 520 494 delete _MMapTree; 521 495 delete _MClrTree; 522 496 delete _FullTree; 523 497 delete _TypeTree; 524 498 525 free(_frameSizes); 526 free(_frameTypes); 527 free(_videoFrameBuffer); 499 delete[] _frameSizes; 500 delete[] _frameTypes; 528 501 free(_palette); 502 503 reset(); 529 504 } 530 505 531 boolSmackerDecoder::decodeNextFrame() {506 Surface *SmackerDecoder::decodeNextFrame() { 532 507 uint i; 533 508 uint32 chunkSize = 0; 534 509 uint32 dataSizeUnpacked = 0; 535 510 536 511 uint32 startPos = _fileStream->pos(); 537 512 538 _ videoInfo.currentFrame++;513 _curFrame++; 539 514 540 if (_videoInfo.currentFrame == 0)541 _videoInfo.startTime = g_system->getMillis();542 543 515 // Check if we got a frame with palette data, and 544 516 // call back the virtual setPalette function to set 545 517 // the current palette 546 if (_frameTypes[_ videoInfo.currentFrame] & 1) {518 if (_frameTypes[_curFrame] & 1) { 547 519 unpackPalette(); 548 setPalette(_palette);520 _dirtyPalette = true; 549 521 } 550 522 551 523 // Load audio tracks 552 524 for (i = 0; i < 7; ++i) { 553 if (!(_frameTypes[_ videoInfo.currentFrame] & (2 << i)))525 if (!(_frameTypes[_curFrame] & (2 << i))) 554 526 continue; 555 527 556 528 chunkSize = _fileStream->readUint32LE(); … … 598 570 } 599 571 } 600 572 601 uint32 frameSize = _frameSizes[_ videoInfo.currentFrame] & ~3;573 uint32 frameSize = _frameSizes[_curFrame] & ~3; 602 574 603 575 if (_fileStream->pos() - startPos > frameSize) 604 e xit(1);576 error("Smacker actual frame size exceeds recorded frame size"); 605 577 606 578 uint32 frameDataSize = frameSize - (_fileStream->pos() - startPos); 607 579 … … 615 587 _FullTree->reset(); 616 588 _TypeTree->reset(); 617 589 618 uint bw = _videoInfo.width / 4; 619 uint bh = _videoInfo.height / 4; 620 uint stride = _videoInfo.width; 621 uint block = 0, blocks = bw*bh; 622 590 // Height needs to be doubled if we have flags (Y-interlaced or Y-doubled) 623 591 uint doubleY = _header.flags ? 2 : 1; 624 592 593 uint bw = getWidth() / 4; 594 uint bh = getHeight() / doubleY / 4; 595 uint stride = getWidth(); 596 uint block = 0, blocks = bw*bh; 597 625 598 byte *out; 626 599 uint type, run, j, mode; 627 600 uint32 p1, p2, clr, map; … … 636 609 while (run-- && block < blocks) { 637 610 clr = _MClrTree->getCode(bs); 638 611 map = _MMapTree->getCode(bs); 639 out = _videoFrameBuffer+ (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;612 out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; 640 613 hi = clr >> 8; 641 614 lo = clr & 0xff; 642 615 for (i = 0; i < 4; i++) { … … 669 642 } 670 643 671 644 while (run-- && block < blocks) { 672 out = _videoFrameBuffer+ (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;645 out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; 673 646 switch (mode) { 674 647 case 0: 675 648 for (i = 0; i < 4; ++i) { … … 735 708 uint32 col; 736 709 mode = type >> 8; 737 710 while (run-- && block < blocks) { 738 out = _videoFrameBuffer+ (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4;711 out = (byte *)_surface->pixels + (block / bw) * (stride * 4 * doubleY) + (block % bw) * 4; 739 712 col = mode * 0x01010101; 740 713 for (i = 0; i < 4 * doubleY; ++i) { 741 714 out[0] = out[1] = out[2] = out[3] = col; … … 751 724 752 725 free(_frameData); 753 726 754 return !endOfVideo(); 727 if (_curFrame == 0) 728 _startTime = g_system->getMillis(); 729 730 return _surface; 755 731 } 756 732 757 733 void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, … … 806 782 // If the sample is stereo, the data is stored for the left and right channel, respectively 807 783 // (the exact opposite to the base values) 808 784 if (!is16Bits) { 809 810 785 for (int k = 0; k < (isStereo ? 2 : 1); k++) { 811 786 bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS)); 812 787 *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80; 813 788 curPos++; 814 789 } 815 816 790 } else { 817 818 791 for (int k = 0; k < (isStereo ? 2 : 1); k++) { 819 792 bases[k] += (int16) (audioTrees[k * 2]->getCode(audioBS) | 820 793 (audioTrees[k * 2 + 1]->getCode(audioBS) << 8)); … … 887 860 } 888 861 889 862 _fileStream->seek(startPos + len); 890 891 863 free(chunk); 892 864 } 893 865 -
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 Common::Rational 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_decoder.cpp
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/graphics/video/video_decoder.cpp $ 22 * $Id$ 23 * 24 */ 25 26 #include "graphics/video/video_decoder.h" 27 28 #include "common/file.h" 29 #include "common/system.h" 30 31 namespace Graphics { 32 33 VideoDecoder::VideoDecoder() { 34 reset(); 35 } 36 37 bool VideoDecoder::loadFile(const Common::String &filename) { 38 Common::File *file = new Common::File(); 39 40 if (!file->open(filename)) { 41 delete file; 42 return false; 43 } 44 45 return load(*file); 46 } 47 48 uint32 VideoDecoder::getElapsedTime() const { 49 return g_system->getMillis() - _startTime; 50 } 51 52 void VideoDecoder::setSystemPalette() { 53 byte *vidPalette = getPalette(); 54 byte *sysPalette = new byte[256 * 4]; 55 56 for (uint16 i = 0; i < 256; i++) { 57 sysPalette[i * 4] = vidPalette[i * 3]; 58 sysPalette[i * 4 + 1] = vidPalette[i * 3 + 1]; 59 sysPalette[i * 4 + 2] = vidPalette[i * 3 + 2]; 60 sysPalette[i * 4 + 3] = 0; 61 } 62 63 g_system->setPalette(sysPalette, 0, 256); 64 delete[] sysPalette; 65 } 66 67 bool VideoDecoder::needsUpdate() const { 68 return !endOfVideo() && getTimeToNextFrame() == 0; 69 } 70 71 void VideoDecoder::reset() { 72 _curFrame = -1; 73 _startTime = 0; 74 } 75 76 bool VideoDecoder::endOfVideo() const { 77 return !isVideoLoaded() || getCurFrame() >= (int32)getFrameCount() - 1; 78 } 79 80 uint32 FixedRateVideoDecoder::getTimeToNextFrame() const { 81 if (endOfVideo() || _curFrame < 0) 82 return 0; 83 84 uint32 elapsedTime = getElapsedTime(); 85 uint32 nextFrameStartTime = getFrameBeginTime(_curFrame + 1); 86 87 // If the time that the next frame should be shown has past 88 // the frame should be shown ASAP. 89 if (nextFrameStartTime <= elapsedTime) 90 return 0; 91 92 return nextFrameStartTime - elapsedTime; 93 } 94 95 uint32 FixedRateVideoDecoder::getFrameBeginTime(uint32 frame) const { 96 Common::Rational beginTime = frame * 1000; 97 beginTime /= getFrameRate(); 98 return beginTime.toInt(); 99 } 100 101 } // End of namespace Graphics
