annotate bink.c @ 11245:1e9ff636c3db libavcodec

Make Bink decoder to stop decoding planes after all bits are used. This prevents crashes during decoding grayscale Bink files like samples from Impossible Creatures game demo.
author kostya
date Mon, 22 Feb 2010 12:35:12 +0000
parents eb773ca000d9
children b48dd9213016
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
1 /*
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
2 * Bink video decoder
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
3 * Copyright (c) 2009 Konstantin Shishkov
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
4 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
5 * This file is part of FFmpeg.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
6 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
11 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
15 * Lesser General Public License for more details.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
16 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
20 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
21
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
22 #include "avcodec.h"
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
23 #include "dsputil.h"
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
24 #include "binkdata.h"
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
25 #include "mathops.h"
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
26
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
27 #define ALT_BITSTREAM_READER_LE
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
28 #include "get_bits.h"
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
29
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
30 static VLC bink_trees[16];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
31
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
32 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
33 * IDs for different data types used in Bink video codec
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
34 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
35 enum Sources {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
36 BINK_SRC_BLOCK_TYPES = 0, ///< 8x8 block types
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
37 BINK_SRC_SUB_BLOCK_TYPES, ///< 16x16 block types (a subset of 8x8 block types)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
38 BINK_SRC_COLORS, ///< pixel values used for different block types
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
39 BINK_SRC_PATTERN, ///< 8-bit values for 2-colour pattern fill
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
40 BINK_SRC_X_OFF, ///< X components of motion value
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
41 BINK_SRC_Y_OFF, ///< Y components of motion value
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
42 BINK_SRC_INTRA_DC, ///< DC values for intrablocks with DCT
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
43 BINK_SRC_INTER_DC, ///< DC values for intrablocks with DCT
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
44 BINK_SRC_RUN, ///< run lengths for special fill block
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
45
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
46 BINK_NB_SRC
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
47 };
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
48
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
49 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
50 * data needed to decode 4-bit Huffman-coded value
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
51 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
52 typedef struct Tree {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
53 int vlc_num; ///< tree number (in bink_trees[])
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
54 uint8_t syms[16]; ///< leaf value to symbol mapping
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
55 } Tree;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
56
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
57 #define GET_HUFF(gb, tree) (tree).syms[get_vlc2(gb, bink_trees[(tree).vlc_num].table,\
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
58 bink_trees[(tree).vlc_num].bits, 1)]
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
59
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
60 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
61 * data structure used for decoding single Bink data type
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
62 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
63 typedef struct Bundle {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
64 int len; ///< length of number of entries to decode (in bits)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
65 Tree tree; ///< Huffman tree-related data
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
66 uint8_t *data; ///< buffer for decoded symbols
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
67 uint8_t *data_end; ///< buffer end
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
68 uint8_t *cur_dec; ///< pointer to the not yet decoded part of the buffer
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
69 uint8_t *cur_ptr; ///< pointer to the data that is not read from buffer yet
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
70 } Bundle;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
71
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
72 /*
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
73 * Decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
74 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
75 typedef struct BinkContext {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
76 AVCodecContext *avctx;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
77 DSPContext dsp;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
78 AVFrame pic, last;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
79 int version; ///< internal Bink file version
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
80 int swap_planes;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
81 ScanTable scantable; ///< permutated scantable for DCT coeffs decoding
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
82
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
83 Bundle bundle[BINK_NB_SRC]; ///< bundles for decoding all data types
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
84 Tree col_high[16]; ///< trees for decoding high nibble in "colours" data type
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
85 int col_lastval; ///< value of last decoded high nibble in "colours" data type
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
86 } BinkContext;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
87
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
88 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
89 * Bink video block types
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
90 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
91 enum BlockTypes {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
92 SKIP_BLOCK = 0, ///< skipped block
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
93 SCALED_BLOCK, ///< block has size 16x16
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
94 MOTION_BLOCK, ///< block is copied from previous frame with some offset
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
95 RUN_BLOCK, ///< block is composed from runs of colours with custom scan order
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
96 RESIDUE_BLOCK, ///< motion block with some difference added
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
97 INTRA_BLOCK, ///< intra DCT block
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
98 FILL_BLOCK, ///< block is filled with single colour
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
99 INTER_BLOCK, ///< motion block with DCT applied to the difference
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
100 PATTERN_BLOCK, ///< block is filled with two colours following custom pattern
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
101 RAW_BLOCK, ///< uncoded 8x8 block
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
102 };
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
103
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
104 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
105 * Initializes length length in all bundles.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
106 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
107 * @param c decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
108 * @param width plane width
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
109 * @param bw plane width in 8x8 blocks
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
110 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
111 static void init_lengths(BinkContext *c, int width, int bw)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
112 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
113 c->bundle[BINK_SRC_BLOCK_TYPES].len = av_log2((width >> 3) + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
114
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
115 c->bundle[BINK_SRC_SUB_BLOCK_TYPES].len = av_log2((width >> 4) + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
116
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
117 c->bundle[BINK_SRC_COLORS].len = av_log2((width >> 3)*64 + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
118
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
119 c->bundle[BINK_SRC_INTRA_DC].len =
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
120 c->bundle[BINK_SRC_INTER_DC].len =
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
121 c->bundle[BINK_SRC_X_OFF].len =
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
122 c->bundle[BINK_SRC_Y_OFF].len = av_log2((width >> 3) + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
123
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
124 c->bundle[BINK_SRC_PATTERN].len = av_log2((bw << 3) + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
125
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
126 c->bundle[BINK_SRC_RUN].len = av_log2((width >> 3)*48 + 511) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
127 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
128
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
129 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
130 * Allocates memory for bundles.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
131 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
132 * @param c decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
133 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
134 static av_cold void init_bundles(BinkContext *c)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
135 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
136 int bw, bh, blocks;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
137 int i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
138
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
139 bw = (c->avctx->width + 7) >> 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
140 bh = (c->avctx->height + 7) >> 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
141 blocks = bw * bh;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
142
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
143 for (i = 0; i < BINK_NB_SRC; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
144 c->bundle[i].data = av_malloc(blocks * 64);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
145 c->bundle[i].data_end = c->bundle[i].data + blocks * 64;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
146 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
147 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
148
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
149 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
150 * Frees memory used by bundles.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
151 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
152 * @param c decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
153 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
154 static av_cold void free_bundles(BinkContext *c)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
155 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
156 int i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
157 for (i = 0; i < BINK_NB_SRC; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
158 av_freep(&c->bundle[i].data);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
159 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
160
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
161 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
162 * Merges two consequent lists of equal size depending on bits read.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
163 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
164 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
165 * @param dst buffer where merged list will be written to
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
166 * @param src pointer to the head of the first list (the second lists starts at src+size)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
167 * @param size input lists size
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
168 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
169 static void merge(GetBitContext *gb, uint8_t *dst, uint8_t *src, int size)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
170 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
171 uint8_t *src2 = src + size;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
172 int size2 = size;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
173
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
174 do {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
175 if (!get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
176 *dst++ = *src++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
177 size--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
178 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
179 *dst++ = *src2++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
180 size2--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
181 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
182 } while (size && size2);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
183
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
184 while (size--)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
185 *dst++ = *src++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
186 while (size2--)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
187 *dst++ = *src2++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
188 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
189
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
190 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
191 * Reads information about Huffman tree used to decode data.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
192 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
193 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
194 * @param tree pointer for storing tree data
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
195 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
196 static void read_tree(GetBitContext *gb, Tree *tree)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
197 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
198 uint8_t tmp1[16], tmp2[16], *in = tmp1, *out = tmp2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
199 int i, t, len;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
200
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
201 tree->vlc_num = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
202 if (!tree->vlc_num) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
203 for (i = 0; i < 16; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
204 tree->syms[i] = i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
205 return;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
206 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
207 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
208 len = get_bits(gb, 3);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
209 memset(tmp1, 0, sizeof(tmp1));
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
210 for (i = 0; i <= len; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
211 tree->syms[i] = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
212 tmp1[tree->syms[i]] = 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
213 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
214 for (i = 0; i < 16; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
215 if (!tmp1[i])
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
216 tree->syms[++len] = i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
217 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
218 len = get_bits(gb, 2);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
219 for (i = 0; i < 16; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
220 in[i] = i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
221 for (i = 0; i <= len; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
222 int size = 1 << i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
223 for (t = 0; t < 16; t += size << 1)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
224 merge(gb, out + t, in + t, size);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
225 FFSWAP(uint8_t*, in, out);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
226 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
227 memcpy(tree->syms, in, 16);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
228 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
229 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
230
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
231 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
232 * Prepares bundle for decoding data.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
233 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
234 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
235 * @param c decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
236 * @param bundle_num number of the bundle to initialize
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
237 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
238 static void read_bundle(GetBitContext *gb, BinkContext *c, int bundle_num)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
239 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
240 int i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
241
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
242 if (bundle_num == BINK_SRC_COLORS) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
243 for (i = 0; i < 16; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
244 read_tree(gb, &c->col_high[i]);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
245 c->col_lastval = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
246 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
247 if (bundle_num != BINK_SRC_INTRA_DC && bundle_num != BINK_SRC_INTER_DC)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
248 read_tree(gb, &c->bundle[bundle_num].tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
249 c->bundle[bundle_num].cur_dec =
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
250 c->bundle[bundle_num].cur_ptr = c->bundle[bundle_num].data;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
251 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
252
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
253 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
254 * common check before starting decoding bundle data
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
255 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
256 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
257 * @param b bundle
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
258 * @param t variable where number of elements to decode will be stored
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
259 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
260 #define CHECK_READ_VAL(gb, b, t) \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
261 if (!b->cur_dec || (b->cur_dec > b->cur_ptr)) \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
262 return 0; \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
263 t = get_bits(gb, b->len); \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
264 if (!t) { \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
265 b->cur_dec = NULL; \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
266 return 0; \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
267 } \
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
268
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
269 static int read_runs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
270 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
271 int t, v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
272 const uint8_t *dec_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
273
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
274 CHECK_READ_VAL(gb, b, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
275 dec_end = b->cur_dec + t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
276 if (dec_end > b->data_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
277 av_log(avctx, AV_LOG_ERROR, "Run value went out of bounds\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
278 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
279 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
280 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
281 v = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
282 memset(b->cur_dec, v, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
283 b->cur_dec += t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
284 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
285 while (b->cur_dec < dec_end)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
286 *b->cur_dec++ = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
287 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
288 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
289 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
290
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
291 static int read_motion_values(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
292 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
293 int t, sign, v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
294 const uint8_t *dec_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
295
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
296 CHECK_READ_VAL(gb, b, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
297 dec_end = b->cur_dec + t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
298 if (dec_end > b->data_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
299 av_log(avctx, AV_LOG_ERROR, "Too many motion values\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
300 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
301 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
302 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
303 v = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
304 if (v) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
305 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
306 v = (v ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
307 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
308 memset(b->cur_dec, v, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
309 b->cur_dec += t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
310 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
311 do {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
312 v = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
313 if (v) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
314 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
315 v = (v ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
316 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
317 *b->cur_dec++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
318 } while (b->cur_dec < dec_end);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
319 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
320 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
321 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
322
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
323 const uint8_t bink_rlelens[4] = { 4, 8, 12, 32 };
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
324
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
325 static int read_block_types(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
326 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
327 int t, v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
328 int last = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
329 const uint8_t *dec_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
330
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
331 CHECK_READ_VAL(gb, b, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
332 dec_end = b->cur_dec + t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
333 if (dec_end > b->data_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
334 av_log(avctx, AV_LOG_ERROR, "Too many block type values\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
335 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
336 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
337 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
338 v = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
339 memset(b->cur_dec, v, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
340 b->cur_dec += t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
341 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
342 do {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
343 v = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
344 if (v < 12) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
345 last = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
346 *b->cur_dec++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
347 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
348 int run = bink_rlelens[v - 12];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
349
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
350 memset(b->cur_dec, last, run);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
351 b->cur_dec += run;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
352 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
353 } while (b->cur_dec < dec_end);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
354 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
355 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
356 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
357
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
358 static int read_patterns(AVCodecContext *avctx, GetBitContext *gb, Bundle *b)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
359 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
360 int t, v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
361 const uint8_t *dec_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
362
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
363 CHECK_READ_VAL(gb, b, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
364 dec_end = b->cur_dec + t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
365 if (dec_end > b->data_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
366 av_log(avctx, AV_LOG_ERROR, "Too many pattern values\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
367 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
368 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
369 while (b->cur_dec < dec_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
370 v = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
371 v |= GET_HUFF(gb, b->tree) << 4;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
372 *b->cur_dec++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
373 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
374
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
375 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
376 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
377
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
378 static int read_colors(GetBitContext *gb, Bundle *b, BinkContext *c)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
379 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
380 int t, sign, v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
381 const uint8_t *dec_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
382
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
383 CHECK_READ_VAL(gb, b, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
384 dec_end = b->cur_dec + t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
385 if (dec_end > b->data_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
386 av_log(c->avctx, AV_LOG_ERROR, "Too many color values\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
387 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
388 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
389 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
390 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
391 v = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
392 v = (c->col_lastval << 4) | v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
393 if (c->version < 'i') {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
394 sign = ((int8_t) v) >> 7;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
395 v = ((v & 0x7F) ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
396 v += 0x80;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
397 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
398 memset(b->cur_dec, v, t);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
399 b->cur_dec += t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
400 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
401 while (b->cur_dec < dec_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
402 c->col_lastval = GET_HUFF(gb, c->col_high[c->col_lastval]);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
403 v = GET_HUFF(gb, b->tree);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
404 v = (c->col_lastval << 4) | v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
405 if (c->version < 'i') {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
406 sign = ((int8_t) v) >> 7;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
407 v = ((v & 0x7F) ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
408 v += 0x80;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
409 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
410 *b->cur_dec++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
411 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
412 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
413 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
414 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
415
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
416 /** number of bits used to store first DC value in bundle */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
417 #define DC_START_BITS 11
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
418
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
419 static int read_dcs(AVCodecContext *avctx, GetBitContext *gb, Bundle *b,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
420 int start_bits, int has_sign)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
421 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
422 int i, j, len, len2, bsize, sign, v, v2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
423 int16_t *dst = (int16_t*)b->cur_dec;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
424
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
425 CHECK_READ_VAL(gb, b, len);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
426 v = get_bits(gb, start_bits - has_sign);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
427 if (v && has_sign) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
428 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
429 v = (v ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
430 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
431 *dst++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
432 len--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
433 for (i = 0; i < len; i += 8) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
434 len2 = FFMIN(len - i, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
435 bsize = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
436 if (bsize) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
437 for (j = 0; j < len2; j++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
438 v2 = get_bits(gb, bsize);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
439 if (v2) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
440 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
441 v2 = (v2 ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
442 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
443 v += v2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
444 *dst++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
445 if (v < -32768 || v > 32767) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
446 av_log(avctx, AV_LOG_ERROR, "DC value went out of bounds: %d\n", v);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
447 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
448 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
449 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
450 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
451 for (j = 0; j < len2; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
452 *dst++ = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
453 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
454 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
455
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
456 b->cur_dec = (uint8_t*)dst;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
457 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
458 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
459
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
460 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
461 * Retrieves next value from bundle.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
462 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
463 * @param c decoder context
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
464 * @param bundle bundle number
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
465 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
466 static inline int get_value(BinkContext *c, int bundle)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
467 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
468 int16_t ret;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
469
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
470 if (bundle < BINK_SRC_X_OFF || bundle == BINK_SRC_RUN)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
471 return *c->bundle[bundle].cur_ptr++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
472 if (bundle == BINK_SRC_X_OFF || bundle == BINK_SRC_Y_OFF)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
473 return (int8_t)*c->bundle[bundle].cur_ptr++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
474 ret = *(int16_t*)c->bundle[bundle].cur_ptr;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
475 c->bundle[bundle].cur_ptr += 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
476 return ret;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
477 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
478
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
479 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
480 * Reads 8x8 block of DCT coefficients.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
481 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
482 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
483 * @param block place for storing coefficients
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
484 * @param scan scan order table
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
485 * @param is_intra tells what set of quantizer matrices to use
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
486 * @return 0 for success, negative value in other cases
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
487 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
488 static int read_dct_coeffs(GetBitContext *gb, DCTELEM block[64], const uint8_t *scan,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
489 int is_intra)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
490 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
491 int coef_list[128];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
492 int mode_list[128];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
493 int i, t, mask, bits, ccoef, mode, sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
494 int list_start = 64, list_end = 64, list_pos;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
495 int coef_count = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
496 int coef_idx[64];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
497 int quant_idx;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
498 const uint32_t *quant;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
499
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
500 coef_list[list_end] = 4; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
501 coef_list[list_end] = 24; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
502 coef_list[list_end] = 44; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
503 coef_list[list_end] = 1; mode_list[list_end++] = 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
504 coef_list[list_end] = 2; mode_list[list_end++] = 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
505 coef_list[list_end] = 3; mode_list[list_end++] = 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
506
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
507 bits = get_bits(gb, 4) - 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
508 for (mask = 1 << bits; bits >= 0; mask >>= 1, bits--) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
509 list_pos = list_start;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
510 while (list_pos < list_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
511 if (!(mode_list[list_pos] | coef_list[list_pos]) || !get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
512 list_pos++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
513 continue;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
514 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
515 ccoef = coef_list[list_pos];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
516 mode = mode_list[list_pos];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
517 switch (mode) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
518 case 0:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
519 coef_list[list_pos] = ccoef + 4;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
520 mode_list[list_pos] = 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
521 case 2:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
522 if (mode == 2) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
523 coef_list[list_pos] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
524 mode_list[list_pos++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
525 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
526 for (i = 0; i < 4; i++, ccoef++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
527 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
528 coef_list[--list_start] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
529 mode_list[ list_start] = 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
530 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
531 int t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
532 if (!bits) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
533 t = 1 - (get_bits1(gb) << 1);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
534 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
535 t = get_bits(gb, bits) | mask;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
536 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
537 t = (t ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
538 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
539 block[scan[ccoef]] = t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
540 coef_idx[coef_count++] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
541 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
542 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
543 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
544 case 1:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
545 mode_list[list_pos] = 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
546 for (i = 0; i < 3; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
547 ccoef += 4;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
548 coef_list[list_end] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
549 mode_list[list_end++] = 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
550 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
551 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
552 case 3:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
553 if (!bits) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
554 t = 1 - (get_bits1(gb) << 1);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
555 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
556 t = get_bits(gb, bits) | mask;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
557 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
558 t = (t ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
559 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
560 block[scan[ccoef]] = t;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
561 coef_idx[coef_count++] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
562 coef_list[list_pos] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
563 mode_list[list_pos++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
564 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
565 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
566 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
567 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
568
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
569 quant_idx = get_bits(gb, 4);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
570 quant = is_intra ? bink_intra_quant[quant_idx]
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
571 : bink_inter_quant[quant_idx];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
572 block[0] = (block[0] * quant[0]) >> 11;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
573 for (i = 0; i < coef_count; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
574 int idx = coef_idx[i];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
575 block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
576 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
577
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
578 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
579 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
580
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
581 /**
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
582 * Reads 8x8 block with residue after motion compensation.
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
583 *
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
584 * @param gb context for reading bits
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
585 * @param block place to store read data
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
586 * @param masks_count number of masks to decode
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
587 * @return 0 on success, negative value in other cases
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
588 */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
589 static int read_residue(GetBitContext *gb, DCTELEM block[64], int masks_count)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
590 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
591 int coef_list[128];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
592 int mode_list[128];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
593 int i, sign, mask, ccoef, mode;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
594 int list_start = 64, list_end = 64, list_pos;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
595 int nz_coeff[64];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
596 int nz_coeff_count = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
597
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
598 coef_list[list_end] = 4; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
599 coef_list[list_end] = 24; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
600 coef_list[list_end] = 44; mode_list[list_end++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
601 coef_list[list_end] = 0; mode_list[list_end++] = 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
602
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
603 for (mask = 1 << get_bits(gb, 3); mask; mask >>= 1) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
604 for (i = 0; i < nz_coeff_count; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
605 if (!get_bits1(gb))
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
606 continue;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
607 if (block[nz_coeff[i]] < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
608 block[nz_coeff[i]] -= mask;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
609 else
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
610 block[nz_coeff[i]] += mask;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
611 masks_count--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
612 if (masks_count < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
613 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
614 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
615 list_pos = list_start;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
616 while (list_pos < list_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
617 if (!(coef_list[list_pos] | mode_list[list_pos]) || !get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
618 list_pos++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
619 continue;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
620 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
621 ccoef = coef_list[list_pos];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
622 mode = mode_list[list_pos];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
623 switch (mode) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
624 case 0:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
625 coef_list[list_pos] = ccoef + 4;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
626 mode_list[list_pos] = 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
627 case 2:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
628 if (mode == 2) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
629 coef_list[list_pos] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
630 mode_list[list_pos++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
631 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
632 for (i = 0; i < 4; i++, ccoef++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
633 if (get_bits1(gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
634 coef_list[--list_start] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
635 mode_list[ list_start] = 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
636 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
637 nz_coeff[nz_coeff_count++] = bink_scan[ccoef];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
638 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
639 block[bink_scan[ccoef]] = (mask ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
640 masks_count--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
641 if (masks_count < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
642 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
643 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
644 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
645 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
646 case 1:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
647 mode_list[list_pos] = 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
648 for (i = 0; i < 3; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
649 ccoef += 4;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
650 coef_list[list_end] = ccoef;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
651 mode_list[list_end++] = 2;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
652 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
653 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
654 case 3:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
655 nz_coeff[nz_coeff_count++] = bink_scan[ccoef];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
656 sign = -get_bits1(gb);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
657 block[bink_scan[ccoef]] = (mask ^ sign) - sign;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
658 coef_list[list_pos] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
659 mode_list[list_pos++] = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
660 masks_count--;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
661 if (masks_count < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
662 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
663 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
664 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
665 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
666 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
667
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
668 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
669 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
670
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
671 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *pkt)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
672 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
673 BinkContext * const c = avctx->priv_data;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
674 GetBitContext gb;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
675 int blk;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
676 int i, j, plane, plane_idx, bx, by;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
677 uint8_t *dst, *prev, *ref, *ref_start, *ref_end;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
678 int v, col[2];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
679 const uint8_t *scan;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
680 int xoff, yoff;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
681 DECLARE_ALIGNED_16(DCTELEM, block[64]);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
682 DECLARE_ALIGNED_16(uint8_t, ublock[64]);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
683 int coordmap[64];
11245
1e9ff636c3db Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents: 11244
diff changeset
684 int bits_count = pkt->size << 3;
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
685
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
686 if(c->pic.data[0])
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
687 avctx->release_buffer(avctx, &c->pic);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
688
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
689 if(avctx->get_buffer(avctx, &c->pic) < 0){
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
690 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
691 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
692 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
693
11245
1e9ff636c3db Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents: 11244
diff changeset
694 init_get_bits(&gb, pkt->data, bits_count);
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
695 if (c->version >= 'i')
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
696 skip_bits_long(&gb, 32);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
697
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
698 for (plane = 0; plane < 3; plane++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
699 const int stride = c->pic.linesize[plane];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
700 int bw = plane ? (avctx->width + 15) >> 4 : (avctx->width + 7) >> 3;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
701 int bh = plane ? (avctx->height + 15) >> 4 : (avctx->height + 7) >> 3;
11244
eb773ca000d9 Correct bundle lengths calculation for small Bink files.
kostya
parents: 11231
diff changeset
702 int width = avctx->width >> !!plane;
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
703
11244
eb773ca000d9 Correct bundle lengths calculation for small Bink files.
kostya
parents: 11231
diff changeset
704 init_lengths(c, FFMAX(width, 8), bw);
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
705 for (i = 0; i < BINK_NB_SRC; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
706 read_bundle(&gb, c, i);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
707
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
708 plane_idx = (!plane || !c->swap_planes) ? plane : (plane ^ 3);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
709 ref_start = c->last.data[plane_idx];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
710 ref_end = c->last.data[plane_idx]
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
711 + (bw - 1 + c->last.linesize[plane_idx] * (bh - 1)) * 8;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
712
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
713 for (i = 0; i < 64; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
714 coordmap[i] = (i & 7) + (i >> 3) * stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
715
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
716 for (by = 0; by < bh; by++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
717 if (read_block_types(avctx, &gb, &c->bundle[BINK_SRC_BLOCK_TYPES]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
718 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
719 if (read_block_types(avctx, &gb, &c->bundle[BINK_SRC_SUB_BLOCK_TYPES]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
720 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
721 if (read_colors(&gb, &c->bundle[BINK_SRC_COLORS], c) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
722 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
723 if (read_patterns(avctx, &gb, &c->bundle[BINK_SRC_PATTERN]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
724 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
725 if (read_motion_values(avctx, &gb, &c->bundle[BINK_SRC_X_OFF]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
726 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
727 if (read_motion_values(avctx, &gb, &c->bundle[BINK_SRC_Y_OFF]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
728 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
729 if (read_dcs(avctx, &gb, &c->bundle[BINK_SRC_INTRA_DC], DC_START_BITS, 0) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
730 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
731 if (read_dcs(avctx, &gb, &c->bundle[BINK_SRC_INTER_DC], DC_START_BITS, 1) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
732 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
733 if (read_runs(avctx, &gb, &c->bundle[BINK_SRC_RUN]) < 0)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
734 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
735
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
736 if (by == bh)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
737 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
738 dst = c->pic.data[plane_idx] + 8*by*stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
739 prev = c->last.data[plane_idx] + 8*by*stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
740 for (bx = 0; bx < bw; bx++, dst += 8, prev += 8) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
741 blk = get_value(c, BINK_SRC_BLOCK_TYPES);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
742 // 16x16 block type on odd line means part of the already decoded block, so skip it
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
743 if ((by & 1) && blk == SCALED_BLOCK) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
744 bx++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
745 dst += 8;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
746 prev += 8;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
747 continue;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
748 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
749 switch (blk) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
750 case SKIP_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
751 c->dsp.put_pixels_tab[1][0](dst, prev, stride, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
752 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
753 case SCALED_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
754 blk = get_value(c, BINK_SRC_SUB_BLOCK_TYPES);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
755 switch (blk) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
756 case RUN_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
757 scan = bink_patterns[get_bits(&gb, 4)];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
758 i = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
759 do {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
760 int run = get_value(c, BINK_SRC_RUN) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
761
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
762 i += run;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
763 if (i > 64) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
764 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
765 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
766 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
767 if (get_bits1(&gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
768 v = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
769 for (j = 0; j < run; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
770 ublock[*scan++] = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
771 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
772 for (j = 0; j < run; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
773 ublock[*scan++] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
774 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
775 } while (i < 63);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
776 if (i == 63)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
777 ublock[*scan++] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
778 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
779 case INTRA_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
780 c->dsp.clear_block(block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
781 block[0] = get_value(c, BINK_SRC_INTRA_DC);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
782 read_dct_coeffs(&gb, block, c->scantable.permutated, 1);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
783 c->dsp.idct(block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
784 c->dsp.put_pixels_nonclamped(block, ublock, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
785 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
786 case FILL_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
787 v = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
788 c->dsp.fill_block_tab[0](dst, v, stride, 16);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
789 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
790 case PATTERN_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
791 for (i = 0; i < 2; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
792 col[i] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
793 for (j = 0; j < 8; j++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
794 v = get_value(c, BINK_SRC_PATTERN);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
795 for (i = 0; i < 8; i++, v >>= 1)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
796 ublock[i + j*8] = col[v & 1];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
797 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
798 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
799 case RAW_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
800 for (j = 0; j < 8; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
801 for (i = 0; i < 8; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
802 ublock[i + j*8] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
803 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
804 default:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
805 av_log(avctx, AV_LOG_ERROR, "Incorrect 16x16 block type %d\n", blk);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
806 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
807 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
808 if (blk != FILL_BLOCK)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
809 c->dsp.scale_block(ublock, dst, stride);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
810 bx++;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
811 dst += 8;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
812 prev += 8;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
813 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
814 case MOTION_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
815 xoff = get_value(c, BINK_SRC_X_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
816 yoff = get_value(c, BINK_SRC_Y_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
817 ref = prev + xoff + yoff * stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
818 if (ref < ref_start || ref > ref_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
819 av_log(avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n",
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
820 bx*8 + xoff, by*8 + yoff);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
821 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
822 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
823 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
824 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
825 case RUN_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
826 scan = bink_patterns[get_bits(&gb, 4)];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
827 i = 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
828 do {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
829 int run = get_value(c, BINK_SRC_RUN) + 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
830
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
831 i += run;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
832 if (i > 64) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
833 av_log(avctx, AV_LOG_ERROR, "Run went out of bounds\n");
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
834 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
835 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
836 if (get_bits1(&gb)) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
837 v = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
838 for (j = 0; j < run; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
839 dst[coordmap[*scan++]] = v;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
840 } else {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
841 for (j = 0; j < run; j++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
842 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
843 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
844 } while (i < 63);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
845 if (i == 63)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
846 dst[coordmap[*scan++]] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
847 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
848 case RESIDUE_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
849 xoff = get_value(c, BINK_SRC_X_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
850 yoff = get_value(c, BINK_SRC_Y_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
851 ref = prev + xoff + yoff * stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
852 if (ref < ref_start || ref > ref_end) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
853 av_log(avctx, AV_LOG_ERROR, "Copy out of bounds @%d, %d\n",
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
854 bx*8 + xoff, by*8 + yoff);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
855 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
856 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
857 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
858 c->dsp.clear_block(block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
859 v = get_bits(&gb, 7);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
860 read_residue(&gb, block, v);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
861 c->dsp.add_pixels8(dst, block, stride);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
862 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
863 case INTRA_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
864 c->dsp.clear_block(block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
865 block[0] = get_value(c, BINK_SRC_INTRA_DC);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
866 read_dct_coeffs(&gb, block, c->scantable.permutated, 1);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
867 c->dsp.idct_put(dst, stride, block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
868 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
869 case FILL_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
870 v = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
871 c->dsp.fill_block_tab[1](dst, v, stride, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
872 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
873 case INTER_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
874 xoff = get_value(c, BINK_SRC_X_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
875 yoff = get_value(c, BINK_SRC_Y_OFF);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
876 ref = prev + xoff + yoff * stride;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
877 c->dsp.put_pixels_tab[1][0](dst, ref, stride, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
878 c->dsp.clear_block(block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
879 block[0] = get_value(c, BINK_SRC_INTER_DC);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
880 read_dct_coeffs(&gb, block, c->scantable.permutated, 0);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
881 c->dsp.idct_add(dst, stride, block);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
882 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
883 case PATTERN_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
884 for (i = 0; i < 2; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
885 col[i] = get_value(c, BINK_SRC_COLORS);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
886 for (i = 0; i < 8; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
887 v = get_value(c, BINK_SRC_PATTERN);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
888 for (j = 0; j < 8; j++, v >>= 1)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
889 dst[i*stride + j] = col[v & 1];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
890 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
891 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
892 case RAW_BLOCK:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
893 for (i = 0; i < 8; i++)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
894 memcpy(dst + i*stride, c->bundle[BINK_SRC_COLORS].cur_ptr + i*8, 8);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
895 c->bundle[BINK_SRC_COLORS].cur_ptr += 64;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
896 break;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
897 default:
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
898 av_log(avctx, AV_LOG_ERROR, "Unknown block type %d\n", blk);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
899 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
900 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
901 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
902 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
903 if (get_bits_count(&gb) & 0x1F) //next plane data starts at 32-bit boundary
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
904 skip_bits_long(&gb, 32 - (get_bits_count(&gb) & 0x1F));
11245
1e9ff636c3db Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents: 11244
diff changeset
905 if (get_bits_count(&gb) >= bits_count)
1e9ff636c3db Make Bink decoder to stop decoding planes after all bits are used.
kostya
parents: 11244
diff changeset
906 break;
11231
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
907 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
908 emms_c();
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
909
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
910 *data_size = sizeof(AVFrame);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
911 *(AVFrame*)data = c->pic;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
912
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
913 FFSWAP(AVFrame, c->pic, c->last);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
914
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
915 /* always report that the buffer was completely consumed */
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
916 return pkt->size;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
917 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
918
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
919 static av_cold int decode_init(AVCodecContext *avctx)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
920 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
921 BinkContext * const c = avctx->priv_data;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
922 static VLC_TYPE table[16 * 128][2];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
923 int i;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
924
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
925 c->version = avctx->codec_tag >> 24;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
926 if (c->version < 'c') {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
927 av_log(avctx, AV_LOG_ERROR, "Too old version '%c'\n", c->version);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
928 return -1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
929 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
930 c->swap_planes = c->version >= 'i';
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
931 if (!bink_trees[15].table) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
932 for (i = 0; i < 16; i++) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
933 const int maxbits = bink_tree_lens[i][15];
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
934 bink_trees[i].table = table + i*128;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
935 bink_trees[i].table_allocated = 1 << maxbits;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
936 init_vlc(&bink_trees[i], maxbits, 16,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
937 bink_tree_lens[i], 1, 1,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
938 bink_tree_bits[i], 1, 1, INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
939 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
940 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
941 c->avctx = avctx;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
942
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
943 c->pic.data[0] = NULL;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
944
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
945 if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
946 return 1;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
947 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
948
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
949 avctx->pix_fmt = PIX_FMT_YUV420P;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
950
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
951 avctx->idct_algo = FF_IDCT_BINK;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
952 dsputil_init(&c->dsp, avctx);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
953 ff_init_scantable(c->dsp.idct_permutation, &c->scantable, bink_scan);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
954
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
955 init_bundles(c);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
956
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
957 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
958 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
959
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
960 static av_cold int decode_end(AVCodecContext *avctx)
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
961 {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
962 BinkContext * const c = avctx->priv_data;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
963
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
964 if (c->pic.data[0])
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
965 avctx->release_buffer(avctx, &c->pic);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
966 if (c->last.data[0])
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
967 avctx->release_buffer(avctx, &c->last);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
968
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
969 free_bundles(c);
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
970 return 0;
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
971 }
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
972
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
973 AVCodec bink_decoder = {
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
974 "binkvideo",
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
975 CODEC_TYPE_VIDEO,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
976 CODEC_ID_BINKVIDEO,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
977 sizeof(BinkContext),
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
978 decode_init,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
979 NULL,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
980 decode_end,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
981 decode_frame,
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
982 .long_name = NULL_IF_CONFIG_SMALL("Bink video"),
0fc1cdd984b7 Bink video decoder
kostya
parents:
diff changeset
983 };