Applied my patch for the BS1/2 video player

- Support for the MPEG2 videos in BS1/2 has been dropped. The MPEG2 videos were lossy, and support for them complicated the code a lot.
- Support for the non-existing enhanced MPEG cutscene packs for BS1 has been dropped. As a consequence, the credits player and the splitted audio stream players used for these packs has been removed
- The original Smacker videos for both games are now supported, using our Smacker player (which is based off publically available specs and FFMPEG)
- The animations now use the common video player code. Both the Smacker videos and our DXA video packs are supported

svn-id: r38236
This commit is contained in:
Filippos Karapetis 2009-02-15 13:29:48 +00:00
parent 47a1cd7545
commit 781d7da6b1
12 changed files with 196 additions and 1315 deletions

View file

@ -42,6 +42,8 @@
#include "sword2/sound.h"
#include "sword2/animation.h"
#include "gui/message.h"
namespace Sword2 {
///////////////////////////////////////////////////////////////////////////////
@ -91,7 +93,6 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm, const char *name) {
_leadOutFrame = (uint)-1;
_seamless = false;
_framesSkipped = 0;
_forceFrame = false;
_currentText = 0;
}
@ -103,43 +104,6 @@ uint32 MoviePlayer::getTick() {
return _system->getMillis() - _pauseTicks;
}
void MoviePlayer::updatePalette(byte *pal, bool packed) {
byte palette[4 * 256];
byte *p = palette;
uint32 maxWeight = 0;
uint32 minWeight = 0xFFFFFFFF;
for (int i = 0; i < 256; i++) {
int r = *pal++;
int g = *pal++;
int b = *pal++;
if (!packed)
pal++;
uint32 weight = 3 * r * r + 6 * g * g + 2 * b * b;
if (weight >= maxWeight) {
_white = i;
maxWeight = weight;
}
if (weight <= minWeight) {
_black = i;
minWeight = i;
}
*p++ = r;
*p++ = g;
*p++ = b;
*p++ = 0;
}
_vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
_forceFrame = true;
}
void MoviePlayer::savePalette() {
memcpy(_originalPalette, _vm->_screen->getPalette(), sizeof(_originalPalette));
}
@ -157,11 +121,6 @@ void MoviePlayer::updateScreen() {
}
bool MoviePlayer::checkSkipFrame() {
if (_forceFrame) {
_forceFrame = false;
return false;
}
if (_framesSkipped > 10) {
warning("Forced frame %d to be displayed", _currentFrame);
_framesSkipped = 0;
@ -512,6 +471,48 @@ void MoviePlayer::pauseMovie(bool pause) {
}
}
///////////////////////////////////////////////////////////////////////////////
// Movie player for the original SMK movies
///////////////////////////////////////////////////////////////////////////////
MoviePlayerSMK::MoviePlayerSMK(Sword2Engine *vm, const char *name)
: MoviePlayer(vm, name), SMKPlayer(vm->_mixer) {
debug(0, "Creating SMK cutscene player");
}
MoviePlayerSMK::~MoviePlayerSMK() {
closeFile();
}
bool MoviePlayerSMK::decodeFrame() {
decodeNextFrame();
copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
return true;
}
bool MoviePlayerSMK::load() {
if (!MoviePlayer::load())
return false;
char filename[20];
snprintf(filename, sizeof(filename), "%s.smk", _name);
if (loadFile(filename)) {
_frameBuffer = _vm->_screen->getScreen();
_frameWidth = getWidth();
_frameHeight = getHeight();
_frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
_frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
return true;
}
return false;
}
#ifdef USE_ZLIB
///////////////////////////////////////////////////////////////////////////////
@ -527,10 +528,6 @@ MoviePlayerDXA::~MoviePlayerDXA() {
closeFile();
}
void MoviePlayerDXA::setPalette(byte *pal) {
updatePalette(pal);
}
bool MoviePlayerDXA::decodeFrame() {
decodeNextFrame();
copyFrameToBuffer(_frameBuffer, _frameX, _frameY, _vm->_screen->getScreenWide());
@ -566,199 +563,6 @@ bool MoviePlayerDXA::load() {
#endif
#ifdef USE_MPEG2
///////////////////////////////////////////////////////////////////////////////
// Movie player for the old MPEG movies
///////////////////////////////////////////////////////////////////////////////
MoviePlayerMPEG::MoviePlayerMPEG(Sword2Engine *vm, const char *name)
: MoviePlayer(vm, name) {
#ifdef BACKEND_8BIT
debug(0, "Creating MPEG cutscene player (8-bit)");
#else
debug(0, "Creating MPEG cutscene player (16-bit)");
#endif
}
MoviePlayerMPEG::~MoviePlayerMPEG() {
delete _anim;
_anim = NULL;
}
bool MoviePlayerMPEG::load() {
if (!MoviePlayer::load())
return false;
_anim = new AnimationState(_vm, this);
if (!_anim->init(_name)) {
delete _anim;
_anim = NULL;
return false;
}
#ifdef BACKEND_8BIT
_frameBuffer = _vm->_screen->getScreen();
#endif
return true;
}
bool MoviePlayerMPEG::decodeFrame() {
bool result = _anim->decodeFrame();
#ifdef BACKEND_8BIT
_frameWidth = _anim->getFrameWidth();
_frameHeight = _anim->getFrameHeight();
_frameX = (_vm->_screen->getScreenWide() - _frameWidth) / 2;
_frameY = (_vm->_screen->getScreenDeep() - _frameHeight) / 2;
#endif
return result;
}
AnimationState::AnimationState(Sword2Engine *vm, MoviePlayer *player)
: BaseAnimationState(vm->_system, 640, 480) {
_vm = vm;
_player = player;
}
AnimationState::~AnimationState() {
}
#ifdef BACKEND_8BIT
void AnimationState::setPalette(byte *pal) {
_player->updatePalette(pal, false);
}
#else
void MoviePlayerMPEG::handleScreenChanged() {
_anim->handleScreenChanged();
}
void MoviePlayerMPEG::clearFrame() {
_anim->clearFrame();
}
void MoviePlayerMPEG::drawFrame() {
}
void MoviePlayerMPEG::updateScreen() {
_anim->updateScreen();
}
void MoviePlayerMPEG::drawTextObject() {
if (_textObject.textMem && _textSurface) {
_anim->drawTextObject(&_textObject.textSprite, _textSurface);
}
}
void MoviePlayerMPEG::undrawTextObject() {
// As long as we only have subtitles for full-sized cutscenes, we don't
// really need to implement this function.
}
void AnimationState::drawTextObject(SpriteInfo *s, byte *src) {
int moviePitch = _movieScale * _movieWidth;
int textX = _movieScale * s->x;
int textY = _movieScale * (_frameHeight - s->h - 12);
OverlayColor *dst = _overlay + textY * moviePitch + textX;
Graphics::PixelFormat format = _sys->getOverlayFormat();
OverlayColor pen = format.RGBToColor(255, 255, 255);
OverlayColor border = format.RGBToColor(0, 0, 0);
// TODO: Use the AdvMame scalers for the text? Pre-scale it?
for (int y = 0; y < s->h; y++) {
OverlayColor *ptr = dst;
for (int x = 0; x < s->w; x++) {
switch (src[x]) {
case 1:
*ptr++ = border;
if (_movieScale > 1) {
*ptr++ = border;
if (_movieScale > 2)
*ptr++ = border;
}
break;
case 255:
*ptr++ = pen;
if (_movieScale > 1) {
*ptr++ = pen;
if (_movieScale > 2)
*ptr++ = pen;
}
break;
default:
ptr += _movieScale;
break;
}
}
if (_movieScale > 1) {
memcpy(dst + moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
if (_movieScale > 2)
memcpy(dst + 2 * moviePitch, dst, _movieScale * s->w * sizeof(OverlayColor));
}
dst += _movieScale * moviePitch;
src += s->w;
}
}
#endif
void AnimationState::clearFrame() {
#ifdef BACKEND_8BIT
memset(_vm->_screen->getScreen(), 0, _movieWidth * _movieHeight);
#else
Graphics::PixelFormat format = _sys->getOverlayFormat();
OverlayColor black = format.RGBToColor(0, 0, 0);
for (int i = 0; i < _movieScale * _movieWidth * _movieScale * _movieHeight; i++)
_overlay[i] = black;
#endif
}
void AnimationState::drawYUV(int width, int height, byte *const *dat) {
_frameWidth = width;
_frameHeight = height;
#ifdef BACKEND_8BIT
byte *buf = _vm->_screen->getScreen() + ((480 - height) / 2) * RENDERWIDE + (640 - width) / 2;
int x, y;
int ypos = 0;
int cpos = 0;
int linepos = 0;
for (y = 0; y < height; y += 2) {
for (x = 0; x < width; x += 2) {
int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH + 1)) + ((dat[1][cpos] + ROUNDADD) >> SHIFT)) * (BITDEPTH + 1);
cpos++;
buf[linepos ] = _lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
buf[linepos ] = _lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)];
buf[RENDERWIDE + linepos++] = _lut[i + ((dat[0][width + ypos++] + ROUNDADD) >> SHIFT)];
}
linepos += (2 * RENDERWIDE - width);
ypos += width;
}
#else
plotYUV(width, height, dat);
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////////
// Dummy player for subtitled speech only
///////////////////////////////////////////////////////////////////////////////
@ -802,10 +606,10 @@ bool MoviePlayerDummy::decodeFrame() {
byte msgNoCutscenesRU[] = "Po\344uk - to\344\345ko pev\345: hagmute k\344abuwy Ucke\343n, u\344u nocetute ca\343t npoekta u ckava\343te budeo po\344uku";
#if defined(USE_MPEG2) || defined(USE_ZLIB)
#if defined(USE_ZLIB)
byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or visit www.scummvm.org to download cutscene videos";
#else
byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with MPEG2 or ZLib support";
byte msgNoCutscenes[] = "Cutscene - Narration Only: Press ESC to exit, or recompile ScummVM with ZLib support";
#endif
byte *msg;
@ -885,6 +689,12 @@ void MoviePlayerDummy::undrawTextObject() {
MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) {
static char filename[20];
snprintf(filename, sizeof(filename), "%s.smk", name);
if (Common::File::exists(filename)) {
return new MoviePlayerSMK(vm, name);
}
#ifdef USE_ZLIB
snprintf(filename, sizeof(filename), "%s.dxa", name);
@ -893,13 +703,12 @@ MoviePlayer *makeMoviePlayer(Sword2Engine *vm, const char *name) {
}
#endif
#ifdef USE_MPEG2
snprintf(filename, sizeof(filename), "%s.mp2", name);
if (Common::File::exists(filename)) {
return new MoviePlayerMPEG(vm, name);
GUI::MessageDialog dialog("MPEG2 cutscenes are no longer supported", "OK");
dialog.runModal();
}
#endif
return new MoviePlayerDummy(vm, name);
}