VIDEO: Implement setOutputPixelFormat() for BinkDecoder

This commit is contained in:
Cameron Cawley 2023-03-01 20:23:39 +00:00 committed by Eugene Sandulenko
parent d72fee204c
commit adef12d993
13 changed files with 62 additions and 41 deletions

View file

@ -44,7 +44,6 @@ MoviePlayer *CreateBinkPlayer(bool demo) {
BinkPlayer::BinkPlayer(bool demo) : MoviePlayer(), _demo(demo) {
_videoDecoder = new Video::BinkDecoder();
_videoDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
_subtitleIndex = _subtitles.begin();
}
@ -205,7 +204,10 @@ bool BinkPlayer::loadFile(const Common::String &filename) {
Common::SeekableReadStream *bink = nullptr;
bink = new Common::SeekableSubReadStream(stream, startBinkPos, stream->size(), DisposeAfterUse::YES);
return _videoDecoder->loadStream(bink);
if (!_videoDecoder->loadStream(bink))
return false;
_videoDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 8, 16, 24, 0));
return true;
}
} // end of namespace Grim

View file

@ -65,7 +65,6 @@ bool MovieManager::registerMovie(const char *fileName, bool8 fade, bool8 loop) {
g_theMusicManager->StopMusic();
_binkDecoder = new Video::BinkDecoder();
_binkDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
Common::SeekableReadStream *stream = openDiskFileForBinaryStreamRead(fileName);
if (!stream) {
@ -74,6 +73,9 @@ bool MovieManager::registerMovie(const char *fileName, bool8 fade, bool8 loop) {
if (!_binkDecoder->loadStream(stream)) {
return false;
}
_binkDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
if (_binkDecoder->getWidth() != SCREEN_WIDTH) {
_x = (SCREEN_WIDTH / 2) - (_binkDecoder->getWidth() / 2);
}

View file

@ -6182,8 +6182,6 @@ void OptionsManager::DrawSlideShow() {
// This slide is bink compressed
Video::BinkDecoder *binkDecoder = new Video::BinkDecoder();
binkDecoder->setDefaultHighColorFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
Common::MemoryReadStream *stream = new Common::MemoryReadStream((byte *)slideptr, slideLen);
if (!stream) {
Fatal_error("Failed open bink file");
@ -6192,6 +6190,8 @@ void OptionsManager::DrawSlideShow() {
Fatal_error("Failed open bink file");
}
binkDecoder->setOutputPixelFormat(Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 24));
// Verify image dimensions
if (binkDecoder->getWidth() > SCREEN_WIDTH || binkDecoder->getHeight() > SCREEN_DEPTH)
Fatal_error("Slide image is too large to fit screen!");

View file

@ -338,8 +338,8 @@ DragItem::DragItem(Myst3Engine *vm, uint id):
// Load the movie
_movieStream = movieDesc.getData();
_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
_bink.loadStream(_movieStream);
_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
_bink.start();
const Graphics::Surface *frame = _bink.decodeNextFrame();

View file

@ -57,8 +57,8 @@ Dialog::Dialog(Myst3Engine *vm, uint id):
// Load the movie
Common::SeekableReadStream *movieStream = movieDesc.getData();
_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
_bink.loadStream(movieStream);
_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
_bink.start();
const Graphics::Surface *frame = _bink.decodeNextFrame();

View file

@ -73,9 +73,9 @@ Movie::Movie(Myst3Engine *vm, uint16 id) :
loadPosition(binkDesc.getVideoData());
Common::SeekableReadStream *binkStream = binkDesc.getData();
_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
_bink.setSoundType(Audio::Mixer::kSFXSoundType);
_bink.loadStream(binkStream);
_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
if (binkDesc.getType() == Archive::kMultitrackMovie || binkDesc.getType() == Archive::kDialogMovie) {
uint language = ConfMan.getInt("audio_language");

View file

@ -1527,8 +1527,8 @@ void Puzzles::projectorLoadBitmap(uint16 bitmap) {
// Rebuild the complete background image from the frames of the bink movie
Common::SeekableReadStream *movieStream = movieDesc.getData();
Video::BinkDecoder bink;
bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
bink.loadStream(movieStream);
bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
bink.start();
for (uint i = 0; i < 1024; i += 256) {
@ -1554,8 +1554,8 @@ void Puzzles::projectorAddSpotItem(uint16 bitmap, uint16 x, uint16 y) {
// Rebuild the complete background image from the frames of the bink movie
Common::SeekableReadStream *movieStream = movieDesc.getData();
Video::BinkDecoder bink;
bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
bink.loadStream(movieStream);
bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
bink.start();
const Graphics::Surface *frame = bink.decodeNextFrame();

View file

@ -360,8 +360,8 @@ bool MovieSubtitles::loadSubtitles(int32 id) {
// Load the movie
Common::SeekableReadStream *movieStream = movie.getData();
_bink.setDefaultHighColorFormat(Texture::getRGBAPixelFormat());
_bink.loadStream(movieStream);
_bink.setOutputPixelFormat(Texture::getRGBAPixelFormat());
_bink.start();
return true;

View file

@ -65,14 +65,14 @@ int MoviePlayer::load(const Common::String &filename, int flags, int image) {
if (_video->isVideoLoaded())
_video->close();
// Ensure that Bink will use our PixelFormat
_video->setDefaultHighColorFormat(g_system->getScreenFormat());
if (!_video->loadFile(filename)) {
warning("Failed to load video file %s", filename.c_str());
return -1;
}
// Ensure that Bink will use our PixelFormat
_video->setOutputPixelFormat(g_system->getScreenFormat());
_video->start();
debug(1, "Playing video %s", filename.c_str());

View file

@ -41,7 +41,6 @@ FMVScreen::FMVScreen(Gfx::Driver *gfx, Cursor *cursor) :
_bitmap->setSamplingFilter(StarkSettings->getImageSamplingFilter());
_decoder = new Video::BinkDecoder();
_decoder->setDefaultHighColorFormat(_bitmap->getBestPixelFormat());
_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
_surfaceRenderer = _gfx->createSurfaceRenderer();
@ -82,6 +81,7 @@ void FMVScreen::play(const Common::String &name) {
if (!_decoder->isVideoLoaded()) {
error("Could not open %s", name.c_str());
}
_decoder->setOutputPixelFormat(_bitmap->getBestPixelFormat());
_decoder->start();
}

View file

@ -72,9 +72,9 @@ void VisualSmacker::loadBink(Common::SeekableReadStream *stream) {
_decoder = new Video::BinkDecoder();
_decoder->setSoundType(Audio::Mixer::kSFXSoundType);
// We need a format with alpha transparency, so we can't use _bitmap->getBestPixelFormat() here.
_decoder->setDefaultHighColorFormat(Gfx::Driver::getRGBAPixelFormat());
_decoder->loadStream(stream);
// We need a format with alpha transparency, so we can't use _bitmap->getBestPixelFormat() here.
_decoder->setOutputPixelFormat(Gfx::Driver::getRGBAPixelFormat());
init();
}

View file

@ -102,7 +102,7 @@ bool BinkDecoder::loadStream(Common::SeekableReadStream *stream) {
uint32 videoFlags = _bink->readUint32LE();
// BIKh and BIKi swap the chroma planes
addTrack(new BinkVideoTrack(width, height, getDefaultHighColorFormat(), frameCount,
addTrack(new BinkVideoTrack(width, height, frameCount,
Common::Rational(frameRateNum, frameRateDen), (id == kBIKhID || id == kBIKiID), videoFlags & kVideoFlagAlpha, id));
uint32 audioTrackCount = _bink->readUint32LE();
@ -242,8 +242,8 @@ BinkDecoder::AudioInfo::~AudioInfo() {
delete dct;
}
BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) :
_frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id) {
BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id) :
_frameCount(frameCount), _frameRate(frameRate), _swapPlanes(swapPlanes), _hasAlpha(hasAlpha), _id(id), _surface(nullptr) {
_curFrame = -1;
for (int i = 0; i < 16; i++)
@ -269,8 +269,8 @@ BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const G
}
// Make the surface even-sized:
_surfaceHeight = height;
_surfaceWidth = width;
_surfaceHeight = _height = height;
_surfaceWidth = _width = width;
if (height & 1) {
_surfaceHeight++;
@ -279,12 +279,11 @@ BinkDecoder::BinkVideoTrack::BinkVideoTrack(uint32 width, uint32 height, const G
_surfaceWidth++;
}
_surface.create(_surfaceWidth, _surfaceHeight, format);
// Since we over-allocate to make surfaces even-sized
// we need to set the actual VIDEO size back into the
// surface.
_surface.h = height;
_surface.w = width;
_pixelFormat = g_system->getScreenFormat();
// Default to a 32bpp format, if in 8bpp mode
if (_pixelFormat.bytesPerPixel == 1)
_pixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
// Compute the video dimensions in blocks
_yBlockWidth = (width + 7) >> 3;
@ -323,7 +322,11 @@ BinkDecoder::BinkVideoTrack::~BinkVideoTrack() {
_huffman[i] = 0;
}
_surface.free();
if (_surface) {
_surface->free();
delete _surface;
_surface = nullptr;
}
}
Common::Rational BinkDecoder::getFrameRate() {
@ -446,6 +449,16 @@ bool BinkDecoder::BinkVideoTrack::rewind() {
void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
assert(frame.bits);
if (!_surface) {
_surface = new Graphics::Surface();
_surface->create(_surfaceWidth, _surfaceHeight, _pixelFormat);
// Since we over-allocate to make surfaces even-sized
// we need to set the actual VIDEO size back into the
// surface.
_surface->h = _height;
_surface->w = _width;
}
if (_hasAlpha) {
if (_id == kBIKiID)
frame.bits->skip(32);
@ -470,11 +483,11 @@ void BinkDecoder::BinkVideoTrack::decodePacket(VideoFrame &frame) {
// to allow for odd-sized videos.
if (_hasAlpha) {
assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2] && _curPlanes[3]);
YUVToRGBMan.convert420Alpha(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2], _curPlanes[3],
YUVToRGBMan.convert420Alpha(_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2], _curPlanes[3],
_surfaceWidth, _surfaceHeight, _yBlockWidth * 8, _uvBlockWidth * 8);
} else {
assert(_curPlanes[0] && _curPlanes[1] && _curPlanes[2]);
YUVToRGBMan.convert420(&_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
YUVToRGBMan.convert420(_surface, Graphics::YUVToRGBManager::kScaleITU, _curPlanes[0], _curPlanes[1], _curPlanes[2],
_surfaceWidth, _surfaceHeight, _yBlockWidth * 8, _uvBlockWidth * 8);
}
@ -675,8 +688,8 @@ void BinkDecoder::BinkVideoTrack::mergeHuffmanSymbols(VideoFrame &video, byte *d
}
void BinkDecoder::BinkVideoTrack::initBundles() {
uint32 bw = (_surface.w + 7) >> 3;
uint32 bh = (_surface.h + 7) >> 3;
uint32 bw = (_width + 7) >> 3;
uint32 bh = (_height + 7) >> 3;
uint32 blocks = bw * bh;
for (int i = 0; i < kSourceMAX; i++) {
@ -684,8 +697,8 @@ void BinkDecoder::BinkVideoTrack::initBundles() {
_bundles[i].dataEnd = _bundles[i].data + blocks * 64;
}
uint32 cbw[2] = { (uint32)((_surface.w + 7) >> 3), (uint32)((_surface.w + 15) >> 4) };
uint32 cw [2] = { (uint32)( _surface.w ), (uint32)( _surface.w >> 1) };
uint32 cbw[2] = { (uint32)((_width + 7) >> 3), (uint32)((_width + 15) >> 4) };
uint32 cw [2] = { (uint32)( _width ), (uint32)( _width >> 1) };
// Calculate the lengths of an element count in bits
for (int i = 0; i < 2; i++) {

View file

@ -147,15 +147,16 @@ private:
class BinkVideoTrack : public FixedRateVideoTrack {
public:
BinkVideoTrack(uint32 width, uint32 height, const Graphics::PixelFormat &format, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id);
BinkVideoTrack(uint32 width, uint32 height, uint32 frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32 id);
~BinkVideoTrack();
uint16 getWidth() const override { return _surface.w; }
uint16 getHeight() const override{ return _surface.h; }
Graphics::PixelFormat getPixelFormat() const override { return _surface.format; }
uint16 getWidth() const override { return _width; }
uint16 getHeight() const override{ return _height; }
Graphics::PixelFormat getPixelFormat() const override { return _pixelFormat; }
bool setOutputPixelFormat(const Graphics::PixelFormat &format) { _pixelFormat = format; return true; }
int getCurFrame() const override { return _curFrame; }
int getFrameCount() const override { return _frameCount; }
const Graphics::Surface *decodeNextFrame() override { return &_surface; }
const Graphics::Surface *decodeNextFrame() override { return _surface; }
bool isSeekable() const override{ return true; }
bool seek(const Audio::Timestamp &time) override { return true; }
bool rewind() override;
@ -243,7 +244,10 @@ private:
int _curFrame;
int _frameCount;
Graphics::Surface _surface;
Graphics::Surface *_surface;
Graphics::PixelFormat _pixelFormat;
uint16 _width;
uint16 _height;
int _surfaceWidth; ///< The actual surface width
int _surfaceHeight; ///< The actual surface height