diff options
Diffstat (limited to 'video/coktel_decoder.h')
-rw-r--r-- | video/coktel_decoder.h | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/video/coktel_decoder.h b/video/coktel_decoder.h new file mode 100644 index 0000000000..e0c91533a3 --- /dev/null +++ b/video/coktel_decoder.h @@ -0,0 +1,520 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Currently, only GOB and SCI32 games play IMDs and VMDs, so skip compiling if GOB and SCI32 is disabled. +#if !(defined(ENABLE_GOB) || defined(ENABLE_SCI32) || defined(DYNAMIC_MODULES)) + +// Do not compile the CoktelDecoder code + +#else + +#ifndef GRAPHICS_VIDEO_COKTELDECODER_H +#define GRAPHICS_VIDEO_COKTELDECODER_H + +#include "common/list.h" +#include "common/array.h" +#include "common/rect.h" + +#include "graphics/video/video_decoder.h" + +#include "sound/mixer.h" + +namespace Audio { + class QueuingAudioStream; +} + +namespace Graphics { + +class Codec; + +/** + * Decoder for Coktel videos. + * + * Video decoder used in engines: + * - gob + * - sci + */ +class CoktelDecoder : public FixedRateVideoDecoder { +public: + struct State { + /** Set accordingly to what was done. */ + uint32 flags; + /** The id of the spoken words. */ + uint16 speechId; + + State(); + }; + + CoktelDecoder(Audio::Mixer *mixer, + Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~CoktelDecoder(); + + virtual bool seek(int32 frame, int whence = SEEK_SET, bool restart = false) = 0; + + /** Draw directly onto the specified video memory. */ + void setSurfaceMemory(void *mem, uint16 width, uint16 height, uint8 bpp); + /** Reset the video memory. */ + void setSurfaceMemory(); + + const Surface *getSurface() const; + + /** Draw the video starting at this position within the video memory. */ + virtual void setXY(uint16 x, uint16 y); + /** Draw the video at the default position. */ + void setXY(); + + /** Override the video's frame rate. */ + void setFrameRate(Common::Rational frameRate); + + /** Get the video's default X position. */ + uint16 getDefaultX() const; + /** Get the video's default Y position. */ + uint16 getDefaultY() const; + + /** Return a list of rectangles that changed in the last frame. */ + const Common::List<Common::Rect> &getDirtyRects() const; + + bool hasPalette() const; + virtual bool hasVideo() const; + + bool hasSound() const; + bool isSoundEnabled() const; + bool isSoundPlaying() const; + + void enableSound(); + void disableSound(); + + virtual void colorModeChanged(); + + /** Return the coordinates of the specified frame. */ + virtual bool getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height); + + /** Return whether that video has any embedded files. */ + virtual bool hasEmbeddedFiles() const; + + /** Return whether that embedded file exists. */ + virtual bool hasEmbeddedFile(const Common::String &fileName) const; + + /** Return that embedded file. */ + virtual Common::SeekableReadStream *getEmbeddedFile(const Common::String &fileName) const; + + /** Return the current subtitle index. */ + virtual int32 getSubtitleIndex() const; + + /** Is the video paletted or true color? */ + virtual bool isPaletted() const; + + + // VideoDecoder interface + + void close(); + + uint16 getWidth() const; + uint16 getHeight() const; + + uint32 getFrameCount() const; + + const byte *getPalette(); + bool hasDirtyPalette() const; + + uint32 getStaticTimeToNextFrame() const; + +protected: + enum SoundStage { + kSoundNone = 0, ///< No sound. + kSoundLoaded = 1, ///< Sound loaded. + kSoundPlaying = 2, ///< Sound is playing. + kSoundFinished = 3 ///< No more new sound data. + }; + + enum Features { + kFeaturesNone = 0x0000, + kFeaturesPalette = 0x0008, ///< Has an own palette. + kFeaturesDataSize = 0x0020, ///< Suggests a data size. + kFeaturesSound = 0x0040, ///< Has sound. + kFeaturesFrameCoords = 0x0080, ///< Has specific frame coordinates. + kFeaturesStdCoords = 0x0100, ///< Has general standard coordinates. + kFeaturesFramePos = 0x0200, ///< Has a frame positions table. + kFeaturesVideo = 0x0400 ///< Has video. + }; + + Audio::Mixer *_mixer; + Audio::Mixer::SoundType _soundType; + + uint16 _width; + uint16 _height; + + uint16 _x; + uint16 _y; + + uint16 _defaultX; + uint16 _defaultY; + + uint32 _features; + + uint32 _frameCount; + + byte _palette[768]; + bool _paletteDirty; + + bool _ownSurface; + Surface _surface; + + Common::List<Common::Rect> _dirtyRects; + + Common::Rational _frameRate; + + // Current sound state + bool _hasSound; + bool _soundEnabled; + SoundStage _soundStage; + + Audio::QueuingAudioStream *_audioStream; + Audio::SoundHandle _audioHandle; + + bool evaluateSeekFrame(int32 &frame, int whence) const; + + // Surface management + bool hasSurface(); + void createSurface(); + void freeSurface(); + + // Decompression + uint32 deLZ77(byte *dest, const byte *src, uint32 srcSize, uint32 destSize); + void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen); + + // Block rendering + void renderBlockWhole (Surface &dstSurf, const byte *src, Common::Rect &rect); + void renderBlockWhole4X (Surface &dstSurf, const byte *src, Common::Rect &rect); + void renderBlockWhole2Y (Surface &dstSurf, const byte *src, Common::Rect &rect); + void renderBlockSparse (Surface &dstSurf, const byte *src, Common::Rect &rect); + void renderBlockSparse2Y(Surface &dstSurf, const byte *src, Common::Rect &rect); + void renderBlockRLE (Surface &dstSurf, const byte *src, Common::Rect &rect); + + // Sound helper functions + inline void unsignedToSigned(byte *buffer, int length); + + + // FixedRateVideoDecoder interface + + Common::Rational getFrameRate() const; +}; + +class PreIMDDecoder : public CoktelDecoder { +public: + PreIMDDecoder(uint16 width, uint16 height, Audio::Mixer *mixer, + Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~PreIMDDecoder(); + + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); + + + // VideoDecoder interface + + bool load(Common::SeekableReadStream *stream); + void close(); + + bool isVideoLoaded() const; + + const Surface *decodeNextFrame(); + + PixelFormat getPixelFormat() const; + +private: + Common::SeekableReadStream *_stream; + + // Buffer for processed frame data + byte *_videoBuffer; + uint32 _videoBufferSize; + + // Frame decoding + void processFrame(); + void renderFrame(); +}; + +class IMDDecoder : public CoktelDecoder { +public: + IMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~IMDDecoder(); + + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); + + void setXY(uint16 x, uint16 y); + + + // VideoDecoder interface + + bool load(Common::SeekableReadStream *stream); + void close(); + + bool isVideoLoaded() const; + + const Surface *decodeNextFrame(); + + PixelFormat getPixelFormat() const; + +private: + enum Command { + kCommandNextSound = 0xFF00, + kCommandStartSound = 0xFF01, + + kCommandBreak = 0xFFF0, + kCommandBreakSkip0 = 0xFFF1, + kCommandBreakSkip16 = 0xFFF2, + kCommandBreakSkip32 = 0xFFF3, + kCommandBreakMask = 0xFFF8, + + kCommandPalette = 0xFFF4, + kCommandVideoData = 0xFFFC, + + kCommandJump = 0xFFFD + }; + + struct Coord { + int16 left; + int16 top; + int16 right; + int16 bottom; + }; + + Common::SeekableReadStream *_stream; + + byte _version; + + // Standard coordinates gives by the header + int16 _stdX; + int16 _stdY; + int16 _stdWidth; + int16 _stdHeight; + + uint32 _flags; + + uint32 _firstFramePos; ///< Position of the first frame's data within the stream. + uint32 *_framePos; ///< Positions of all frames. + Coord *_frameCoords; ///< Coordinates of all frames. + + uint32 _videoBufferSize; ///< Size of the video buffers. + byte *_videoBuffer[2]; ///< Video buffers. + uint32 _videoBufferLen[2]; ///< Size of the video buffers filled. + + // Sound properties + uint16 _soundFlags; + int16 _soundFreq; + int16 _soundSliceSize; + int16 _soundSlicesCount; + + // Loading helper functions + bool loadCoordinates(); + bool loadFrameTableOffsets(uint32 &framePosPos, uint32 &frameCoordsPos); + bool assessVideoProperties(); + bool assessAudioProperties(); + bool loadFrameTables(uint32 framePosPos, uint32 frameCoordsPos); + + // Frame decoding + void processFrame(); + Common::Rect calcFrameCoords(uint32 frame); + + // Video + bool renderFrame(Common::Rect &rect); + + // Sound + void nextSoundSlice(bool hasNextCmd); + bool initialSoundSlice(bool hasNextCmd); + void emptySoundSlice(bool hasNextCmd); +}; + +class VMDDecoder : public CoktelDecoder { +public: + VMDDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType); + ~VMDDecoder(); + + bool seek(int32 frame, int whence = SEEK_SET, bool restart = false); + + void setXY(uint16 x, uint16 y); + + void colorModeChanged(); + + bool getFrameCoords(int16 frame, int16 &x, int16 &y, int16 &width, int16 &height); + + bool hasEmbeddedFiles() const; + bool hasEmbeddedFile(const Common::String &fileName) const; + Common::SeekableReadStream *getEmbeddedFile(const Common::String &fileName) const; + + int32 getSubtitleIndex() const; + + bool hasVideo() const; + bool isPaletted() const; + + + // VideoDecoder interface + + bool load(Common::SeekableReadStream *stream); + void close(); + + bool isVideoLoaded() const; + + const Surface *decodeNextFrame(); + + PixelFormat getPixelFormat() const; + +private: + enum PartType { + kPartTypeSeparator = 0, + kPartTypeAudio = 1, + kPartTypeVideo = 2, + kPartTypeFile = 3, + kPartType4 = 4, + kPartTypeSubtitle = 5 + }; + + enum AudioFormat { + kAudioFormat8bitRaw = 0, + kAudioFormat16bitDPCM = 1, + kAudioFormat16bitADPCM = 2 + }; + + struct File { + Common::String name; + + uint32 offset; + uint32 size; + uint32 realSize; + + File(); + }; + + struct Part { + PartType type; + byte field_1; + byte field_E; + uint32 size; + int16 left; + int16 top; + int16 right; + int16 bottom; + uint16 id; + byte flags; + + Part(); + }; + + struct Frame { + uint32 offset; + Part *parts; + + Frame(); + ~Frame(); + }; + + // Tables for the audio decompressors + static const uint16 _tableDPCM[128]; + static const int32 _tableADPCM[]; + static const int32 _tableADPCMStep[]; + + Common::SeekableReadStream *_stream; + + byte _version; + uint32 _flags; + + uint32 _frameInfoOffset; + uint16 _partsPerFrame; + Frame *_frames; + + Common::Array<File> _files; + + // Sound properties + uint16 _soundFlags; + int16 _soundFreq; + int16 _soundSliceSize; + int16 _soundSlicesCount; + byte _soundBytesPerSample; + byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo) + uint32 _soundHeaderSize; + uint32 _soundDataSize; + AudioFormat _audioFormat; + + // Video properties + bool _hasVideo; + uint32 _videoCodec; + byte _blitMode; + byte _bytesPerPixel; + + uint32 _firstFramePos; ///< Position of the first frame's data within the stream. + + uint32 _videoBufferSize; ///< Size of the video buffers. + byte *_videoBuffer[3]; ///< Video buffers. + uint32 _videoBufferLen[3]; ///< Size of the video buffers filled. + + Surface _8bppSurface[3]; ///< Fake 8bpp surfaces over the video buffers. + + bool _externalCodec; + Codec *_codec; + + int32 _subtitle; + + bool _isPaletted; + + // Loading helper functions + bool assessVideoProperties(); + bool assessAudioProperties(); + bool openExternalCodec(); + bool readFrameTable(int &numFiles); + bool readFiles(); + + // Frame decoding + void processFrame(); + + // Video + bool renderFrame(Common::Rect &rect); + bool getRenderRects(const Common::Rect &rect, + Common::Rect &realRect, Common::Rect &fakeRect); + void blit16(const Surface &srcSurf, Common::Rect &rect); + void blit24(const Surface &srcSurf, Common::Rect &rect); + + // Sound + void emptySoundSlice (uint32 size); + void filledSoundSlice (uint32 size); + void filledSoundSlices(uint32 size, uint32 mask); + + uint8 evaluateMask(uint32 mask, bool *fillInfo, uint8 &max); + + // Generating sound slices + byte *soundEmpty (uint32 &size); + byte *sound8bitRaw (uint32 &size); + byte *sound16bitDPCM (uint32 &size); + byte *sound16bitADPCM(uint32 &size); + + // Sound decompression + byte *deDPCM (const byte *data, uint32 &size, int32 init[2]); + byte *deADPCM(const byte *data, uint32 &size, int32 init, int32 index); + + bool getPartCoords(int16 frame, PartType type, int16 &x, int16 &y, int16 &width, int16 &height); +}; + +} // End of namespace Graphics + +#endif // GRAPHICS_VIDEO_COKTELDECODER_H + +#endif // Engine and dynamic plugins guard |