OpenGothic
Open source reimplementation of Gothic I and II
Loading...
Searching...
No Matches
video.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <stdexcept>
5#include <vector>
6
7#include "frame.h"
8
9namespace Bink {
10
11class Video;
12
13class SoundDecodingException : public std::runtime_error {
14 SoundDecodingException(const char* msg):std::runtime_error(msg){};
15 friend class Video;
16 };
17
18class VideoDecodingException : public std::runtime_error {
19 VideoDecodingException(const char* msg):std::runtime_error(msg){};
20 friend class Video;
21 };
22
23class Video final {
24 public:
25 enum {
26 BINK_TAG = 1766541634
27 };
28
33
34 class Input {
35 public:
36 virtual ~Input()=default;
37 virtual void read(void* dest, size_t count) = 0;
38 virtual void seek(size_t pos) = 0;
39 virtual void skip(size_t count) = 0;
40 };
41
42 struct FrameRate final {
43 uint32_t num = 1;
44 uint32_t den = 1;
45 };
46
47 struct Audio {
48 uint16_t sampleRate = 44100;
49 bool isMono = false;
50 };
51
52 explicit Video(Input* file);
53 Video(const Video&) = delete;
54 ~Video();
55
56 const Frame& nextFrame();
57 size_t frameCount() const;
58 size_t currentFrame() const { return frameCounter; }
59
60 const FrameRate& fps() const { return fRate; }
61
62 const Frame& frame(uint8_t i) const { return frames[i]; };
63 size_t audioCount() const { return aud.size(); }
64 const Audio& audio(uint8_t i) const { return audProp[i]; }
65
66 struct FFTComplex final {
67 float re, im;
68 };
69
70 private:
71 enum BinkVidFlags : uint32_t {
72 BINK_FLAG_NONE = 0,
73 BINK_FLAG_ALPHA = 0x00100000,
74 BINK_FLAG_GRAY = 0x00020000,
75 };
76 enum BinkAudFlags : uint16_t {
77 BINK_AUD_16BITS = 0x4000,
78 BINK_AUD_STEREO = 0x2000,
79 BINK_AUD_USEDCT = 0x1000,
80 };
81
82 enum Sources {
83 BINK_SRC_BLOCK_TYPES = 0, // 8x8 block types
84 BINK_SRC_SUB_BLOCK_TYPES, // 16x16 block types (a subset of 8x8 block types)
85 BINK_SRC_COLORS, // pixel values used for different block types
86 BINK_SRC_PATTERN, // 8-bit values for 2-colour pattern fill
87 BINK_SRC_X_OFF, // X components of motion value
88 BINK_SRC_Y_OFF, // Y components of motion value
89 BINK_SRC_INTRA_DC, // DC values for intrablocks with DCT
90 BINK_SRC_INTER_DC, // DC values for interblocks with DCT
91 BINK_SRC_RUN, // run lengths for special fill block
92
93 BINK_NB_SRC
94 };
95
96 enum BlockTypes {
97 SKIP_BLOCK = 0, // skipped block
98 SCALED_BLOCK, // block has size 16x16
99 MOTION_BLOCK, // block is copied from previous frame with some offset
100 RUN_BLOCK, // block is composed from runs of colours with custom scan order
101 RESIDUE_BLOCK, // motion block with some difference added
102 INTRA_BLOCK, // intra DCT block
103 FILL_BLOCK, // block is filled with single colour
104 INTER_BLOCK, // motion block with DCT applied to the difference
105 PATTERN_BLOCK, // block is filled with two colours following custom pattern
106 RAW_BLOCK, // uncoded 8x8 block
107 };
108
109 enum {
110 DC_START_BITS = 11,
111 MAX_CHANNELS = 2,
112 BINK_BLOCK_MAX_SIZE = (MAX_CHANNELS << 11)
113 };
114
115 struct AudioTrack {
116 uint32_t id =0;
117 uint16_t sampleRate=0;
118 uint8_t channels =0;
119 };
120
121 struct Index {
122 uint32_t pos = 0;
123 uint32_t size = 0;
124 bool keyFrame = false;
125 };
126
127 struct Tree final {
128 int vlc_num = 0; // tree number (in bink_trees[])
129 uint8_t syms[16] = {}; // leaf value to symbol mapping
130 };
131
132 struct Bundle final {
133 int len = 0; // length of number of entries to decode (in bits)
134 Tree tree; // Huffman tree-related data
135 std::vector<uint8_t> data; // buffer for decoded symbols
136 uint8_t* data_end = nullptr; // buffer end
137 uint8_t* cur_dec = nullptr; // pointer to the not yet decoded part of the buffer
138 uint8_t* cur_ptr = nullptr; // pointer to the data that is not read from buffer yet
139 };
140
141 struct AudioCtx final {
142 AudioCtx(uint16_t sampleRate, uint8_t channelsCnt, bool isDct);
143
144 std::vector<float> samples[MAX_CHANNELS];
145
146 uint32_t sampleRate = 44100;
147 uint8_t channelsCnt = 1;
148 float root = 0.f;
149 uint32_t frameLen = 0;
150 uint32_t overlapLen = 0;
151 int nbits = 0;
152 const bool isDct = false; // discrete cosine transforms
153
154 uint32_t bands[26] = {};
155 uint32_t numBands = 0;
156
157 const float* tcos = nullptr;
158 const float* tsin = nullptr;
159
160 std::vector<uint16_t> revtab;
161 std::vector<uint32_t> revtab32;
162 std::vector<float> csc2;
163
164 std::vector<FFTComplex> tmpBuf;
165 float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE/16]; // coeffs from previous audio block
166
167 bool first = true;
168 };
169
170 struct BitStream;
171
172 uint32_t rl32();
173 uint16_t rl16();
174 void merge(BitStream& gb, uint8_t *dst, uint8_t *src, int size);
175
176 void decodeInit();
177 void decodeAudioInit(AudioCtx& s);
178
179 int setIdx (BitStream& gb, int code, int& n, int& nb_bits, const int16_t (*table)[2]);
180 uint8_t getHuff(BitStream& gb, const Tree& tree);
181 int getVlc2(BitStream& gb, int16_t (*table)[2], int bits, int max_depth);
182 void readPacket();
183 void parseFrame(const std::vector<uint8_t>& data);
184 void decodePlane(BitStream& gb, int planeId, bool chroma);
185 void initLengths(int width, int bw);
186 void readBundle(BitStream& gb, int bundle_num);
187 void readTree(BitStream& gb, Tree& tree);
188
189 void readBlockTypes (BitStream& gb, Bundle& b);
190 void readColors (BitStream& gb, Bundle& b);
191 void readPatterns (BitStream& gb, Bundle& b);
192 void readMotionValues(BitStream& gb, Bundle& b);
193 void readDcs (BitStream& gb, Bundle& b, int start_bits, int has_sign);
194 void readRuns (BitStream& gb, Bundle& b);
195 int readDctCoeffs (BitStream& gb, int32_t block[], const uint8_t* scan,
196 int& coef_count_, int coef_idx[], int q);
197 void unquantizeDctCoeffs(int32_t block[], const uint32_t quant[],
198 int coef_count, int coef_idx[], const uint8_t* scan);
199 void readResidue (BitStream& gb, int16_t block[], int masks_count);
200 int getValue(Sources bundle);
201 template<class T>
202 static bool checkReadVal(BitStream& gb, Bundle& b, T& t);
203
204 void initFfCosTabs(size_t index);
205 void parseAudio(const std::vector<uint8_t>& data, size_t id);
206 void parseAudioBlock(BitStream& gb, AudioCtx& track);
207 void dctCalc3C (AudioCtx& aud, float* data);
208 void rdftCalcC (AudioCtx& aud, float* data, bool negativeSign);
209
210 void fftPermute(AudioCtx& aud, FFTComplex* z);
211 void fftCalc (const AudioCtx& aud, FFTComplex* z);
212
213 Input* fin = nullptr;
214 uint8_t revision = 0;
215 BinkVidFlags flags = BINK_FLAG_NONE;
216 uint32_t width = 0;
217 uint32_t height = 0;
218 uint32_t smush_size = 0;
219 bool swap_planes = false;
220
221 std::vector<Audio> audProp;
222 std::vector<AudioCtx> aud;
223 std::vector<Index> index;
224
225 FrameRate fRate;
226 Frame frames[2] = {};
227
228 std::vector<uint8_t> packet;
229 uint32_t frameCounter = 0;
230
231 // video
232 Bundle bundle[BINK_NB_SRC] = {};
233 Tree col_high[16]; // trees for decoding high nibble in "colours" data type
234 int col_lastval = 0; // value of last decoded high nibble in "colours" data type
235
236 // sound
237 float quantTable[96] = {};
238 };
239
240}
virtual void seek(size_t pos)=0
virtual ~Input()=default
virtual void read(void *dest, size_t count)=0
virtual void skip(size_t count)=0
Video(const Video &)=delete
const Frame & frame(uint8_t i) const
Definition video.h:62
size_t currentFrame() const
Definition video.h:58
const Frame & nextFrame()
Definition video.cpp:928
const FrameRate & fps() const
Definition video.h:60
size_t frameCount() const
Definition video.cpp:943
@ AV_PIX_FMT_YUVA420P
Definition video.h:30
@ AV_PIX_FMT_YUV420P
Definition video.h:31
@ BINK_TAG
Definition video.h:26
size_t audioCount() const
Definition video.h:63
const Audio & audio(uint8_t i) const
Definition video.h:64
Definition frame.h:7
uint16_t sampleRate
Definition video.h:48