Files
2026-02-02 04:50:13 +01:00

143 lines
4.1 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ultima/ultima8/audio/music_process.h"
#include "ultima/ultima8/gfx/avi_player.h"
#include "ultima/ultima8/gfx/render_surface.h"
#include "ultima/ultima8/gfx/texture.h"
#include "video/avi_decoder.h"
namespace Ultima {
namespace Ultima8 {
AVIPlayer::AVIPlayer(Common::SeekableReadStream *rs, int width, int height, const byte *overridePal, bool noScale)
: MoviePlayer(), _playing(false), _width(width), _height(height),
_doubleSize(false), _pausedMusic(false), _overridePal(overridePal) {
_decoder = new Video::AVIDecoder();
_decoder->loadStream(rs);
uint32 vidWidth = _decoder->getWidth();
uint32 vidHeight = _decoder->getHeight();
if (vidWidth <= _width / 2 && vidHeight <= _height / 2 && !noScale) {
_doubleSize = true;
vidHeight *= 2;
vidWidth *= 2;
}
_xoff = _width / 2 - (vidWidth / 2);
_yoff = _height / 2 - (vidHeight / 2);
_currentFrame.create(vidWidth, vidHeight, _decoder->getPixelFormat());
_currentFrame.fillRect(Common::Rect(0, 0, vidWidth, vidHeight),
_decoder->getPixelFormat().RGBToColor(0, 0, 0));
if (_currentFrame.format.bytesPerPixel == 1)
_currentFrame.setTransparentColor(0);
}
AVIPlayer::~AVIPlayer() {
delete _decoder;
}
void AVIPlayer::start() {
MusicProcess *music = MusicProcess::get_instance();
if (music && music->isPlaying()) {
music->pauseMusic();
_pausedMusic = true;
}
_playing = true;
_decoder->start();
}
void AVIPlayer::stop() {
MusicProcess *music = MusicProcess::get_instance();
if (music && _pausedMusic) {
music->unpauseMusic();
_pausedMusic = false;
}
_playing = false;
_decoder->stop();
}
void AVIPlayer::paint(RenderSurface *surf, int /*lerp*/) {
if (_decoder->endOfVideo()) {
_playing = false;
return;
}
if (_decoder->needsUpdate())
{
const Graphics::Surface *frame = _decoder->decodeNextFrame();
if (!frame || _decoder->getCurFrame() < 0) {
// Some sort of decoding error?
_playing = false;
return;
}
if (frame->format.bytesPerPixel == 1) {
const byte *pal;
if (_overridePal)
pal = _overridePal;
else
pal = _decoder->getPalette();
_currentFrame.setPalette(pal, 0, 256);
}
if (_doubleSize) {
// TODO: Add support for multiple bytes per pixel
assert(_currentFrame.w == frame->w * 2 && _currentFrame.h == frame->h * 2);
const int bpp = frame->format.bytesPerPixel;
for (int y = 0; y < frame->h; y++) {
const uint8 *srcPixel = static_cast<const uint8 *>(frame->getPixels()) + frame->pitch * y;
uint8 *dstPixels = static_cast<uint8 *>(_currentFrame.getPixels()) + _currentFrame.pitch * y * 2;
for (int x = 0; x < frame->w; x++) {
for (int i = 0; i < bpp; i++) {
dstPixels[x * 2 * bpp + i] = *srcPixel;
dstPixels[x * 2 * bpp + i + bpp] = *srcPixel;
srcPixel++;
}
}
}
} else {
_currentFrame.blitFrom(*frame);
}
}
uint32 color = TEX32_PACK_RGB(0, 0, 0);
surf->fill32(color, _xoff, _yoff, _currentFrame.w, _currentFrame.h);
Common::Rect srcRect(_currentFrame.w, _currentFrame.h);
surf->Blit(_currentFrame, srcRect, _xoff, _yoff);
}
void AVIPlayer::run() {
if (_decoder->endOfVideo()) {
_playing = false;
}
}
int AVIPlayer::getFrameNo() const {
return _decoder->getCurFrame();
}
void AVIPlayer::setOffset(int xoff, int yoff) {
_xoff = xoff;
_yoff = yoff;
}
} // End of namespace Ultima8
} // End of namespace Ultima