diff --git a/bink.h b/bink.h
new file mode 100644
index 0000000..ab7c0de
--- /dev/null
+++ b/bink.h
@@ -0,0 +1,396 @@
+/* xoreos - A reimplementation of BioWare's Aurora engine
+ *
+ * xoreos is the legal property of its developers, whose names
+ * can be found in the AUTHORS file distributed with this source
+ * distribution.
+ *
+ * xoreos 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.
+ *
+ * xoreos 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 xoreos. If not, see .
+ */
+
+/** @file
+ * Decoding RAD Game Tools' Bink videos.
+ */
+
+/* Based on the Bink implementation in FFmpeg (,
+ * which is released under the terms of version 2 or later of the GNU
+ * Lesser General Public License.
+ *
+ * The original copyright notes in the files
+ * - libavformat/bink.c
+ * - libavcodec/bink.c
+ * - libavcodec/binkdata.h
+ * - libavcodec/binkdsp.c
+ * - libavcodec/binkdsp.h
+ * - libavcodec/binkaudio.c
+ * read as follows:
+ *
+ * Bink demuxer
+ * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org)
+ * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
+ *
+ * Bink video decoder
+ * Copyright (c) 2009 Konstantin Shishkov
+ * Copyright (C) 2011 Peter Ross
+ *
+ * Bink video decoder
+ * Copyright (C) 2009 Konstantin Shishkov
+ *
+ * Bink DSP routines
+ * Copyright (c) 2009 Konstantin Shishkov
+ *
+ * Bink Audio decoder
+ * Copyright (c) 2007-2011 Peter Ross (pross@xvid.org)
+ * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef VIDEO_BINK_H
+#define VIDEO_BINK_H
+
+#include
+#include
+
+#include "src/common/types.h"
+#include "src/common/rational.h"
+
+#include "src/video/decoder.h"
+
+namespace Common {
+ class SeekableReadStream;
+ class BitStream;
+ class Huffman;
+
+ class RDFT;
+ class DCT;
+}
+
+namespace Sound {
+ class PacketizedAudioStream;
+}
+
+namespace Video {
+
+/** A decoder for RAD Game Tools' Bink videos. */
+class Bink : public VideoDecoder {
+public:
+ Bink(Common::SeekableReadStream *bink);
+ ~Bink();
+
+protected:
+ void decodeNextTrackFrame(VideoTrack &track);
+ void checkAudioBuffer(AudioTrack &track, const Common::Timestamp &endTime);
+
+private:
+ static const int kAudioChannelsMax = 2;
+ static const int kAudioBlockSizeMax = (kAudioChannelsMax << 11);
+
+ enum AudioCodec {
+ kAudioCodecDCT,
+ kAudioCodecRDFT
+ };
+
+ /** An audio track. */
+ struct AudioInfo {
+ uint16_t flags;
+
+ uint32_t sampleRate;
+ uint8_t channels;
+
+ uint32_t outSampleRate;
+ uint8_t outChannels;
+
+ AudioCodec codec;
+
+ bool first;
+
+ uint32_t frameLen;
+ uint32_t overlapLen;
+
+ uint32_t blockSize;
+
+ uint32_t bandCount;
+ uint32_t *bands;
+
+ float root;
+
+ float coeffs[16 * kAudioBlockSizeMax];
+ int16_t prevCoeffs[kAudioBlockSizeMax];
+
+ float *coeffsPtr[kAudioChannelsMax];
+
+ Common::RDFT *rdft;
+ Common::DCT *dct;
+
+ AudioInfo();
+ AudioInfo(const AudioInfo &audioInfo) = default;
+ ~AudioInfo();
+ };
+
+ /** A video frame. */
+ struct VideoFrame {
+ bool keyFrame;
+
+ uint32_t offset;
+ uint32_t size;
+
+ Common::BitStream *bits;
+
+ VideoFrame();
+ VideoFrame(const VideoFrame &videoFrame) = default;
+ ~VideoFrame();
+ };
+
+ std::unique_ptr _bink;
+
+ std::vector _audioTracks; ///< All audio tracks.
+ std::vector _frames; ///< All video frames.
+
+ uint32_t _audioTrack; ///< Audio track to use.
+
+ /** Load a Bink file. */
+ void load();
+
+ class BinkVideoTrack : public FixedRateVideoTrack {
+ public:
+ BinkVideoTrack(uint32_t width, uint32_t height, uint32_t frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32_t id);
+
+ uint32_t getWidth() const { return _width; }
+ uint32_t getHeight() const { return _height; }
+ int getCurFrame() const { return _curFrame; }
+ int getFrameCount() const { return _frameCount; }
+
+ /** Decode a video packet. */
+ void decodePacket(Graphics::Surface &surface, VideoFrame &frame);
+
+ protected:
+ Common::Rational getFrameRate() const { return _frameRate; }
+
+ private:
+ /** A decoder state. */
+ struct DecodeContext {
+ VideoFrame *video;
+
+ uint32_t planeIdx;
+
+ uint32_t blockX;
+ uint32_t blockY;
+
+ byte *dest;
+ byte *prev;
+
+ byte *destStart, *destEnd;
+ byte *prevStart, *prevEnd;
+
+ uint32_t pitch;
+
+ int coordMap[64];
+ int coordScaledMap1[64];
+ int coordScaledMap2[64];
+ int coordScaledMap3[64];
+ int coordScaledMap4[64];
+ };
+
+ /** IDs for different data types used in Bink video codec. */
+ enum Source {
+ kSourceBlockTypes = 0, ///< 8x8 block types.
+ kSourceSubBlockTypes , ///< 16x16 block types (a subset of 8x8 block types).
+ kSourceColors , ///< Pixel values used for different block types.
+ kSourcePattern , ///< 8-bit values for 2-color pattern fill.
+ kSourceXOff , ///< X components of motion value.
+ kSourceYOff , ///< Y components of motion value.
+ kSourceIntraDC , ///< DC values for intrablocks with DCT.
+ kSourceInterDC , ///< DC values for interblocks with DCT.
+ kSourceRun , ///< Run lengths for special fill block.
+
+ kSourceMAX
+ };
+
+ /** Bink video block types. */
+ enum BlockType {
+ kBlockSkip = 0, ///< Skipped block.
+ kBlockScaled , ///< Block has size 16x16.
+ kBlockMotion , ///< Block is copied from previous frame with some offset.
+ kBlockRun , ///< Block is composed from runs of colors with custom scan order.
+ kBlockResidue , ///< Motion block with some difference added.
+ kBlockIntra , ///< Intra DCT block.
+ kBlockFill , ///< Block is filled with single color.
+ kBlockInter , ///< Motion block with DCT applied to the difference.
+ kBlockPattern , ///< Block is filled with two colors following custom pattern.
+ kBlockRaw ///< Uncoded 8x8 block.
+ };
+
+ /** Data structure for decoding and translating Huffman'd data. */
+ struct Huffman {
+ int index; ///< Index of the Huffman codebook to use.
+ byte symbols[16]; ///< Huffman symbol => Bink symbol translation list.
+
+ Huffman();
+ };
+
+ /** Data structure used for decoding a single Bink data type. */
+ struct Bundle {
+ int countLengths[2]; ///< Lengths of number of entries to decode (in bits).
+ int countLength; ///< Length of number of entries to decode (in bits) for the current plane.
+
+ Huffman huffman; ///< Huffman codebook.
+
+ std::unique_ptr data; ///< Buffer for decoded symbols.
+
+ byte *dataEnd; ///< Pointer to the data end end.
+ byte *curDec; ///< Pointer to the data that wasn't yet decoded.
+ byte *curPtr; ///< Pointer to the data that wasn't yet read.
+
+ Bundle();
+ };
+
+ uint32_t _width;
+ uint32_t _height;
+
+ int _curFrame; ///< Current Frame.
+ int _frameCount;
+
+ Common::Rational _frameRate; ///< The frame rate of the video.
+
+ bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV?
+ bool _hasAlpha; ///< Do video frames have alpha?
+
+ uint32_t _id; ///< The BIK FourCC.
+
+ Bundle _bundles[kSourceMAX]; ///< Bundles for decoding all data types.
+
+ std::unique_ptr _huffman[16]; ///< The 16 Huffman codebooks used in Bink decoding.
+
+ /** Huffman codebooks to use for decoding high nibbles in color data types. */
+ Huffman _colHighHuffman[16];
+ /** Value of the last decoded high nibble in color data types. */
+ int _colLastVal;
+
+ std::unique_ptr _curPlanes[4]; ///< The 4 color planes, YUVA, current frame.
+ std::unique_ptr _oldPlanes[4]; ///< The 4 color planes, YUVA, last frame.
+
+ /** Initialize the bundles. */
+ void initBundles();
+
+ /** Initialize the Huffman decoders. */
+ void initHuffman();
+
+ /** Decode a video packet. */
+ void videoPacket(VideoFrame &video);
+
+ /** Decode a plane. */
+ void decodePlane(VideoFrame &video, int planeIdx, bool isChroma);
+
+ /** Read/Initialize a bundle for decoding a plane. */
+ void readBundle(VideoFrame &video, Source source);
+
+ /** Read the symbols for a Huffman code. */
+ void readHuffman(VideoFrame &video, Huffman &huffman);
+ /** Merge two Huffman symbol lists. */
+ void mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size);
+
+ /** Read and translate a symbol out of a Huffman code. */
+ byte getHuffmanSymbol(VideoFrame &video, Huffman &huffman);
+
+ /** Get a direct value out of a bundle. */
+ int32_t getBundleValue(Source source);
+ /** Read a count value out of a bundle. */
+ uint32_t readBundleCount(VideoFrame &video, Bundle &bundle);
+
+ // Handle the block types
+ void blockSkip (DecodeContext &ctx);
+ void blockScaledSkip (DecodeContext &ctx);
+ void blockScaledRun (DecodeContext &ctx);
+ void blockScaledIntra (DecodeContext &ctx);
+ void blockScaledFill (DecodeContext &ctx);
+ void blockScaledPattern(DecodeContext &ctx);
+ void blockScaledRaw (DecodeContext &ctx);
+ void blockScaled (DecodeContext &ctx);
+ void blockMotion (DecodeContext &ctx);
+ void blockRun (DecodeContext &ctx);
+ void blockResidue (DecodeContext &ctx);
+ void blockIntra (DecodeContext &ctx);
+ void blockFill (DecodeContext &ctx);
+ void blockInter (DecodeContext &ctx);
+ void blockPattern (DecodeContext &ctx);
+ void blockRaw (DecodeContext &ctx);
+
+ // Read the bundles
+ void readRuns (VideoFrame &video, Bundle &bundle);
+ void readMotionValues(VideoFrame &video, Bundle &bundle);
+ void readBlockTypes (VideoFrame &video, Bundle &bundle);
+ void readPatterns (VideoFrame &video, Bundle &bundle);
+ void readColors (VideoFrame &video, Bundle &bundle);
+ void readDCS (VideoFrame &video, Bundle &bundle, int startBits, bool hasSign);
+ void readDCTCoeffs (VideoFrame &video, int16_t *block, bool isIntra);
+ void readResidue (VideoFrame &video, int16_t *block, int masksCount);
+
+ // Bink video IDCT
+ void IDCT(int16_t *block);
+ void IDCTPut(DecodeContext &ctx, int16_t *block);
+ void IDCTAdd(DecodeContext &ctx, int16_t *block);
+ };
+
+ class BinkAudioTrack : public AudioTrack {
+ public:
+ BinkAudioTrack(size_t index, AudioInfo &audio);
+ ~BinkAudioTrack();
+
+ bool canBufferData() const;
+
+ /** Decode audio data up to endTime. */
+ void decodeAudio(Common::SeekableReadStream& bink, const std::vector& frames, const std::vector& audioTracks, const Common::Timestamp& endTime);
+
+ protected:
+ Sound::AudioStream *getAudioStream() const;
+
+ private:
+ size_t _index;
+ AudioInfo &_info;
+ Sound::PacketizedAudioStream *_audioStream;
+ uint32_t _curFrame;
+ Common::Timestamp _audioBuffered;
+
+ float getFloat(Common::BitStream &bits);
+
+ /** Decode an audio block. */
+ void audioBlock(Common::BitStream &bits, int16_t *out);
+ /** Decode a DCT'd audio block. */
+ void audioBlockDCT(Common::BitStream &bits);
+ /** Decode a RDFT'd audio block. */
+ void audioBlockRDFT(Common::BitStream &bits);
+
+ void readAudioCoeffs(Common::BitStream &bits, float *coeffs);
+
+ static void floatToInt16Interleave(int16_t *dst, const float **src, uint32_t length, uint8_t channels);
+ };
+
+ void initAudioTrack(AudioInfo &audio);
+};
+
+} // End of namespace Video
+
+#endif // VIDEO_BINK_H