This is required for >= 16bit RGB support
I tried it without templates but its too much duplicated code
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
... | ... |
@@ -158,37 +158,6 @@ static av_always_inline int fold(int diff, int bits) |
158 | 158 |
return diff; |
159 | 159 |
} |
160 | 160 |
|
161 |
-static inline int predict(int16_t *src, int16_t *last) |
|
162 |
-{ |
|
163 |
- const int LT = last[-1]; |
|
164 |
- const int T = last[0]; |
|
165 |
- const int L = src[-1]; |
|
166 |
- |
|
167 |
- return mid_pred(L, L + T - LT, T); |
|
168 |
-} |
|
169 |
- |
|
170 |
-static inline int get_context(PlaneContext *p, int16_t *src, |
|
171 |
- int16_t *last, int16_t *last2) |
|
172 |
-{ |
|
173 |
- const int LT = last[-1]; |
|
174 |
- const int T = last[0]; |
|
175 |
- const int RT = last[1]; |
|
176 |
- const int L = src[-1]; |
|
177 |
- |
|
178 |
- if (p->quant_table[3][127]) { |
|
179 |
- const int TT = last2[0]; |
|
180 |
- const int LL = src[-2]; |
|
181 |
- return p->quant_table[0][(L - LT) & 0xFF] + |
|
182 |
- p->quant_table[1][(LT - T) & 0xFF] + |
|
183 |
- p->quant_table[2][(T - RT) & 0xFF] + |
|
184 |
- p->quant_table[3][(LL - L) & 0xFF] + |
|
185 |
- p->quant_table[4][(TT - T) & 0xFF]; |
|
186 |
- } else |
|
187 |
- return p->quant_table[0][(L - LT) & 0xFF] + |
|
188 |
- p->quant_table[1][(LT - T) & 0xFF] + |
|
189 |
- p->quant_table[2][(T - RT) & 0xFF]; |
|
190 |
-} |
|
191 |
- |
|
192 | 161 |
static inline void update_vlc_state(VlcState *const state, const int v) |
193 | 162 |
{ |
194 | 163 |
int drift = state->drift; |
... | ... |
@@ -223,4 +192,10 @@ static inline void update_vlc_state(VlcState *const state, const int v) |
223 | 223 |
state->count = count; |
224 | 224 |
} |
225 | 225 |
|
226 |
+#define TYPE int16_t |
|
227 |
+#define RENAME(name) name |
|
228 |
+#include "ffv1_template.c" |
|
229 |
+#undef TYPE |
|
230 |
+#undef RENAME |
|
231 |
+ |
|
226 | 232 |
#endif /* AVCODEC_FFV1_H */ |
227 | 233 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,53 @@ |
0 |
+/* |
|
1 |
+ * FFV1 codec |
|
2 |
+ * |
|
3 |
+ * Copyright (c) 2003-2013 Michael Niedermayer <michaelni@gmx.at> |
|
4 |
+ * |
|
5 |
+ * This file is part of FFmpeg. |
|
6 |
+ * |
|
7 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
8 |
+ * modify it under the terms of the GNU Lesser General Public |
|
9 |
+ * License as published by the Free Software Foundation; either |
|
10 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
11 |
+ * |
|
12 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 |
+ * Lesser General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU Lesser General Public |
|
18 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
20 |
+ */ |
|
21 |
+ |
|
22 |
+static inline int RENAME(predict)(TYPE *src, TYPE *last) |
|
23 |
+{ |
|
24 |
+ const int LT = last[-1]; |
|
25 |
+ const int T = last[0]; |
|
26 |
+ const int L = src[-1]; |
|
27 |
+ |
|
28 |
+ return mid_pred(L, L + T - LT, T); |
|
29 |
+} |
|
30 |
+ |
|
31 |
+static inline int RENAME(get_context)(PlaneContext *p, TYPE *src, |
|
32 |
+ TYPE *last, TYPE *last2) |
|
33 |
+{ |
|
34 |
+ const int LT = last[-1]; |
|
35 |
+ const int T = last[0]; |
|
36 |
+ const int RT = last[1]; |
|
37 |
+ const int L = src[-1]; |
|
38 |
+ |
|
39 |
+ if (p->quant_table[3][127]) { |
|
40 |
+ const int TT = last2[0]; |
|
41 |
+ const int LL = src[-2]; |
|
42 |
+ return p->quant_table[0][(L - LT) & 0xFF] + |
|
43 |
+ p->quant_table[1][(LT - T) & 0xFF] + |
|
44 |
+ p->quant_table[2][(T - RT) & 0xFF] + |
|
45 |
+ p->quant_table[3][(LL - L) & 0xFF] + |
|
46 |
+ p->quant_table[4][(TT - T) & 0xFF]; |
|
47 |
+ } else |
|
48 |
+ return p->quant_table[0][(L - LT) & 0xFF] + |
|
49 |
+ p->quant_table[1][(LT - T) & 0xFF] + |
|
50 |
+ p->quant_table[2][(T - RT) & 0xFF]; |
|
51 |
+} |
|
52 |
+ |
... | ... |
@@ -97,88 +97,12 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, |
97 | 97 |
return ret; |
98 | 98 |
} |
99 | 99 |
|
100 |
-static av_always_inline void decode_line(FFV1Context *s, int w, |
|
101 |
- int16_t *sample[2], |
|
102 |
- int plane_index, int bits) |
|
103 |
-{ |
|
104 |
- PlaneContext *const p = &s->plane[plane_index]; |
|
105 |
- RangeCoder *const c = &s->c; |
|
106 |
- int x; |
|
107 |
- int run_count = 0; |
|
108 |
- int run_mode = 0; |
|
109 |
- int run_index = s->run_index; |
|
110 |
- |
|
111 |
- if (s->slice_coding_mode == 1) { |
|
112 |
- int i; |
|
113 |
- for (x = 0; x < w; x++) { |
|
114 |
- int v = 0; |
|
115 |
- for (i=0; i<bits; i++) { |
|
116 |
- uint8_t state = 128; |
|
117 |
- v += v + get_rac(c, &state); |
|
118 |
- } |
|
119 |
- sample[1][x] = v; |
|
120 |
- } |
|
121 |
- return; |
|
122 |
- } |
|
100 |
+#define TYPE int16_t |
|
101 |
+#define RENAME(name) name |
|
102 |
+#include "ffv1dec_template.c" |
|
103 |
+#undef TYPE |
|
104 |
+#undef RENAME |
|
123 | 105 |
|
124 |
- for (x = 0; x < w; x++) { |
|
125 |
- int diff, context, sign; |
|
126 |
- |
|
127 |
- context = get_context(p, sample[1] + x, sample[0] + x, sample[1] + x); |
|
128 |
- if (context < 0) { |
|
129 |
- context = -context; |
|
130 |
- sign = 1; |
|
131 |
- } else |
|
132 |
- sign = 0; |
|
133 |
- |
|
134 |
- av_assert2(context < p->context_count); |
|
135 |
- |
|
136 |
- if (s->ac != AC_GOLOMB_RICE) { |
|
137 |
- diff = get_symbol_inline(c, p->state[context], 1); |
|
138 |
- } else { |
|
139 |
- if (context == 0 && run_mode == 0) |
|
140 |
- run_mode = 1; |
|
141 |
- |
|
142 |
- if (run_mode) { |
|
143 |
- if (run_count == 0 && run_mode == 1) { |
|
144 |
- if (get_bits1(&s->gb)) { |
|
145 |
- run_count = 1 << ff_log2_run[run_index]; |
|
146 |
- if (x + run_count <= w) |
|
147 |
- run_index++; |
|
148 |
- } else { |
|
149 |
- if (ff_log2_run[run_index]) |
|
150 |
- run_count = get_bits(&s->gb, ff_log2_run[run_index]); |
|
151 |
- else |
|
152 |
- run_count = 0; |
|
153 |
- if (run_index) |
|
154 |
- run_index--; |
|
155 |
- run_mode = 2; |
|
156 |
- } |
|
157 |
- } |
|
158 |
- run_count--; |
|
159 |
- if (run_count < 0) { |
|
160 |
- run_mode = 0; |
|
161 |
- run_count = 0; |
|
162 |
- diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], |
|
163 |
- bits); |
|
164 |
- if (diff >= 0) |
|
165 |
- diff++; |
|
166 |
- } else |
|
167 |
- diff = 0; |
|
168 |
- } else |
|
169 |
- diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); |
|
170 |
- |
|
171 |
- ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", |
|
172 |
- run_count, run_index, run_mode, x, get_bits_count(&s->gb)); |
|
173 |
- } |
|
174 |
- |
|
175 |
- if (sign) |
|
176 |
- diff = -diff; |
|
177 |
- |
|
178 |
- sample[1][x] = av_mod_uintp2(predict(sample[1] + x, sample[0] + x) + diff, bits); |
|
179 |
- } |
|
180 |
- s->run_index = run_index; |
|
181 |
-} |
|
182 | 106 |
|
183 | 107 |
static void decode_plane(FFV1Context *s, uint8_t *src, |
184 | 108 |
int w, int h, int stride, int plane_index, |
... | ... |
@@ -223,62 +147,6 @@ static void decode_plane(FFV1Context *s, uint8_t *src, |
223 | 223 |
} |
224 | 224 |
} |
225 | 225 |
|
226 |
-static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) |
|
227 |
-{ |
|
228 |
- int x, y, p; |
|
229 |
- int16_t *sample[4][2]; |
|
230 |
- int lbd = s->avctx->bits_per_raw_sample <= 8; |
|
231 |
- int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; |
|
232 |
- int offset = 1 << bits; |
|
233 |
- |
|
234 |
- for (x = 0; x < 4; x++) { |
|
235 |
- sample[x][0] = s->sample_buffer + x * 2 * (w + 6) + 3; |
|
236 |
- sample[x][1] = s->sample_buffer + (x * 2 + 1) * (w + 6) + 3; |
|
237 |
- } |
|
238 |
- |
|
239 |
- s->run_index = 0; |
|
240 |
- |
|
241 |
- memset(s->sample_buffer, 0, 8 * (w + 6) * sizeof(*s->sample_buffer)); |
|
242 |
- |
|
243 |
- for (y = 0; y < h; y++) { |
|
244 |
- for (p = 0; p < 3 + s->transparency; p++) { |
|
245 |
- int16_t *temp = sample[p][0]; // FIXME: try a normal buffer |
|
246 |
- |
|
247 |
- sample[p][0] = sample[p][1]; |
|
248 |
- sample[p][1] = temp; |
|
249 |
- |
|
250 |
- sample[p][1][-1]= sample[p][0][0 ]; |
|
251 |
- sample[p][0][ w]= sample[p][0][w-1]; |
|
252 |
- if (lbd && s->slice_coding_mode == 0) |
|
253 |
- decode_line(s, w, sample[p], (p + 1)/2, 9); |
|
254 |
- else |
|
255 |
- decode_line(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1)); |
|
256 |
- } |
|
257 |
- for (x = 0; x < w; x++) { |
|
258 |
- int g = sample[0][1][x]; |
|
259 |
- int b = sample[1][1][x]; |
|
260 |
- int r = sample[2][1][x]; |
|
261 |
- int a = sample[3][1][x]; |
|
262 |
- |
|
263 |
- if (s->slice_coding_mode != 1) { |
|
264 |
- b -= offset; |
|
265 |
- r -= offset; |
|
266 |
- g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; |
|
267 |
- b += g; |
|
268 |
- r += g; |
|
269 |
- } |
|
270 |
- |
|
271 |
- if (lbd) |
|
272 |
- *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24); |
|
273 |
- else { |
|
274 |
- *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; |
|
275 |
- *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; |
|
276 |
- *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; |
|
277 |
- } |
|
278 |
- } |
|
279 |
- } |
|
280 |
-} |
|
281 |
- |
|
282 | 226 |
static int decode_slice_header(FFV1Context *f, FFV1Context *fs) |
283 | 227 |
{ |
284 | 228 |
RangeCoder *c = &fs->c; |
285 | 229 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,160 @@ |
0 |
+/* |
|
1 |
+ * FFV1 decoder template |
|
2 |
+ * |
|
3 |
+ * Copyright (c) 2003-2016 Michael Niedermayer <michaelni@gmx.at> |
|
4 |
+ * |
|
5 |
+ * This file is part of FFmpeg. |
|
6 |
+ * |
|
7 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
8 |
+ * modify it under the terms of the GNU Lesser General Public |
|
9 |
+ * License as published by the Free Software Foundation; either |
|
10 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
11 |
+ * |
|
12 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 |
+ * Lesser General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU Lesser General Public |
|
18 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
20 |
+ */ |
|
21 |
+ |
|
22 |
+static av_always_inline void RENAME(decode_line)(FFV1Context *s, int w, |
|
23 |
+ TYPE *sample[2], |
|
24 |
+ int plane_index, int bits) |
|
25 |
+{ |
|
26 |
+ PlaneContext *const p = &s->plane[plane_index]; |
|
27 |
+ RangeCoder *const c = &s->c; |
|
28 |
+ int x; |
|
29 |
+ int run_count = 0; |
|
30 |
+ int run_mode = 0; |
|
31 |
+ int run_index = s->run_index; |
|
32 |
+ |
|
33 |
+ if (s->slice_coding_mode == 1) { |
|
34 |
+ int i; |
|
35 |
+ for (x = 0; x < w; x++) { |
|
36 |
+ int v = 0; |
|
37 |
+ for (i=0; i<bits; i++) { |
|
38 |
+ uint8_t state = 128; |
|
39 |
+ v += v + get_rac(c, &state); |
|
40 |
+ } |
|
41 |
+ sample[1][x] = v; |
|
42 |
+ } |
|
43 |
+ return; |
|
44 |
+ } |
|
45 |
+ |
|
46 |
+ for (x = 0; x < w; x++) { |
|
47 |
+ int diff, context, sign; |
|
48 |
+ |
|
49 |
+ context = RENAME(get_context)(p, sample[1] + x, sample[0] + x, sample[1] + x); |
|
50 |
+ if (context < 0) { |
|
51 |
+ context = -context; |
|
52 |
+ sign = 1; |
|
53 |
+ } else |
|
54 |
+ sign = 0; |
|
55 |
+ |
|
56 |
+ av_assert2(context < p->context_count); |
|
57 |
+ |
|
58 |
+ if (s->ac != AC_GOLOMB_RICE) { |
|
59 |
+ diff = get_symbol_inline(c, p->state[context], 1); |
|
60 |
+ } else { |
|
61 |
+ if (context == 0 && run_mode == 0) |
|
62 |
+ run_mode = 1; |
|
63 |
+ |
|
64 |
+ if (run_mode) { |
|
65 |
+ if (run_count == 0 && run_mode == 1) { |
|
66 |
+ if (get_bits1(&s->gb)) { |
|
67 |
+ run_count = 1 << ff_log2_run[run_index]; |
|
68 |
+ if (x + run_count <= w) |
|
69 |
+ run_index++; |
|
70 |
+ } else { |
|
71 |
+ if (ff_log2_run[run_index]) |
|
72 |
+ run_count = get_bits(&s->gb, ff_log2_run[run_index]); |
|
73 |
+ else |
|
74 |
+ run_count = 0; |
|
75 |
+ if (run_index) |
|
76 |
+ run_index--; |
|
77 |
+ run_mode = 2; |
|
78 |
+ } |
|
79 |
+ } |
|
80 |
+ run_count--; |
|
81 |
+ if (run_count < 0) { |
|
82 |
+ run_mode = 0; |
|
83 |
+ run_count = 0; |
|
84 |
+ diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], |
|
85 |
+ bits); |
|
86 |
+ if (diff >= 0) |
|
87 |
+ diff++; |
|
88 |
+ } else |
|
89 |
+ diff = 0; |
|
90 |
+ } else |
|
91 |
+ diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); |
|
92 |
+ |
|
93 |
+ ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", |
|
94 |
+ run_count, run_index, run_mode, x, get_bits_count(&s->gb)); |
|
95 |
+ } |
|
96 |
+ |
|
97 |
+ if (sign) |
|
98 |
+ diff = -diff; |
|
99 |
+ |
|
100 |
+ sample[1][x] = av_mod_uintp2(RENAME(predict)(sample[1] + x, sample[0] + x) + diff, bits); |
|
101 |
+ } |
|
102 |
+ s->run_index = run_index; |
|
103 |
+} |
|
104 |
+ |
|
105 |
+static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) |
|
106 |
+{ |
|
107 |
+ int x, y, p; |
|
108 |
+ TYPE *sample[4][2]; |
|
109 |
+ int lbd = s->avctx->bits_per_raw_sample <= 8; |
|
110 |
+ int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; |
|
111 |
+ int offset = 1 << bits; |
|
112 |
+ |
|
113 |
+ for (x = 0; x < 4; x++) { |
|
114 |
+ sample[x][0] = RENAME(s->sample_buffer) + x * 2 * (w + 6) + 3; |
|
115 |
+ sample[x][1] = RENAME(s->sample_buffer) + (x * 2 + 1) * (w + 6) + 3; |
|
116 |
+ } |
|
117 |
+ |
|
118 |
+ s->run_index = 0; |
|
119 |
+ |
|
120 |
+ memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer))); |
|
121 |
+ |
|
122 |
+ for (y = 0; y < h; y++) { |
|
123 |
+ for (p = 0; p < 3 + s->transparency; p++) { |
|
124 |
+ TYPE *temp = sample[p][0]; // FIXME: try a normal buffer |
|
125 |
+ |
|
126 |
+ sample[p][0] = sample[p][1]; |
|
127 |
+ sample[p][1] = temp; |
|
128 |
+ |
|
129 |
+ sample[p][1][-1]= sample[p][0][0 ]; |
|
130 |
+ sample[p][0][ w]= sample[p][0][w-1]; |
|
131 |
+ if (lbd && s->slice_coding_mode == 0) |
|
132 |
+ RENAME(decode_line)(s, w, sample[p], (p + 1)/2, 9); |
|
133 |
+ else |
|
134 |
+ RENAME(decode_line)(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1)); |
|
135 |
+ } |
|
136 |
+ for (x = 0; x < w; x++) { |
|
137 |
+ int g = sample[0][1][x]; |
|
138 |
+ int b = sample[1][1][x]; |
|
139 |
+ int r = sample[2][1][x]; |
|
140 |
+ int a = sample[3][1][x]; |
|
141 |
+ |
|
142 |
+ if (s->slice_coding_mode != 1) { |
|
143 |
+ b -= offset; |
|
144 |
+ r -= offset; |
|
145 |
+ g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; |
|
146 |
+ b += g; |
|
147 |
+ r += g; |
|
148 |
+ } |
|
149 |
+ |
|
150 |
+ if (lbd) |
|
151 |
+ *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24); |
|
152 |
+ else { |
|
153 |
+ *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; |
|
154 |
+ *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; |
|
155 |
+ *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; |
|
156 |
+ } |
|
157 |
+ } |
|
158 |
+ } |
|
159 |
+} |
... | ... |
@@ -268,107 +268,12 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, |
268 | 268 |
update_vlc_state(state, v); |
269 | 269 |
} |
270 | 270 |
|
271 |
-static av_always_inline int encode_line(FFV1Context *s, int w, |
|
272 |
- int16_t *sample[3], |
|
273 |
- int plane_index, int bits) |
|
274 |
-{ |
|
275 |
- PlaneContext *const p = &s->plane[plane_index]; |
|
276 |
- RangeCoder *const c = &s->c; |
|
277 |
- int x; |
|
278 |
- int run_index = s->run_index; |
|
279 |
- int run_count = 0; |
|
280 |
- int run_mode = 0; |
|
281 |
- |
|
282 |
- if (s->ac != AC_GOLOMB_RICE) { |
|
283 |
- if (c->bytestream_end - c->bytestream < w * 35) { |
|
284 |
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
|
285 |
- return AVERROR_INVALIDDATA; |
|
286 |
- } |
|
287 |
- } else { |
|
288 |
- if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < w * 4) { |
|
289 |
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
|
290 |
- return AVERROR_INVALIDDATA; |
|
291 |
- } |
|
292 |
- } |
|
293 |
- |
|
294 |
- if (s->slice_coding_mode == 1) { |
|
295 |
- for (x = 0; x < w; x++) { |
|
296 |
- int i; |
|
297 |
- int v = sample[0][x]; |
|
298 |
- for (i = bits-1; i>=0; i--) { |
|
299 |
- uint8_t state = 128; |
|
300 |
- put_rac(c, &state, (v>>i) & 1); |
|
301 |
- } |
|
302 |
- } |
|
303 |
- return 0; |
|
304 |
- } |
|
305 |
- |
|
306 |
- for (x = 0; x < w; x++) { |
|
307 |
- int diff, context; |
|
308 |
- |
|
309 |
- context = get_context(p, sample[0] + x, sample[1] + x, sample[2] + x); |
|
310 |
- diff = sample[0][x] - predict(sample[0] + x, sample[1] + x); |
|
311 |
- |
|
312 |
- if (context < 0) { |
|
313 |
- context = -context; |
|
314 |
- diff = -diff; |
|
315 |
- } |
|
316 |
- |
|
317 |
- diff = fold(diff, bits); |
|
318 |
- |
|
319 |
- if (s->ac != AC_GOLOMB_RICE) { |
|
320 |
- if (s->flags & AV_CODEC_FLAG_PASS1) { |
|
321 |
- put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, |
|
322 |
- s->rc_stat2[p->quant_table_index][context]); |
|
323 |
- } else { |
|
324 |
- put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL); |
|
325 |
- } |
|
326 |
- } else { |
|
327 |
- if (context == 0) |
|
328 |
- run_mode = 1; |
|
329 |
- |
|
330 |
- if (run_mode) { |
|
331 |
- if (diff) { |
|
332 |
- while (run_count >= 1 << ff_log2_run[run_index]) { |
|
333 |
- run_count -= 1 << ff_log2_run[run_index]; |
|
334 |
- run_index++; |
|
335 |
- put_bits(&s->pb, 1, 1); |
|
336 |
- } |
|
337 |
- |
|
338 |
- put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count); |
|
339 |
- if (run_index) |
|
340 |
- run_index--; |
|
341 |
- run_count = 0; |
|
342 |
- run_mode = 0; |
|
343 |
- if (diff > 0) |
|
344 |
- diff--; |
|
345 |
- } else { |
|
346 |
- run_count++; |
|
347 |
- } |
|
348 |
- } |
|
349 |
- |
|
350 |
- ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", |
|
351 |
- run_count, run_index, run_mode, x, |
|
352 |
- (int)put_bits_count(&s->pb)); |
|
353 |
- |
|
354 |
- if (run_mode == 0) |
|
355 |
- put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits); |
|
356 |
- } |
|
357 |
- } |
|
358 |
- if (run_mode) { |
|
359 |
- while (run_count >= 1 << ff_log2_run[run_index]) { |
|
360 |
- run_count -= 1 << ff_log2_run[run_index]; |
|
361 |
- run_index++; |
|
362 |
- put_bits(&s->pb, 1, 1); |
|
363 |
- } |
|
271 |
+#define TYPE int16_t |
|
272 |
+#define RENAME(name) name |
|
273 |
+#include "ffv1enc_template.c" |
|
274 |
+#undef TYPE |
|
275 |
+#undef RENAME |
|
364 | 276 |
|
365 |
- if (run_count) |
|
366 |
- put_bits(&s->pb, 1, 1); |
|
367 |
- } |
|
368 |
- s->run_index = run_index; |
|
369 |
- |
|
370 |
- return 0; |
|
371 |
-} |
|
372 | 277 |
|
373 | 278 |
static int encode_plane(FFV1Context *s, uint8_t *src, int w, int h, |
374 | 279 |
int stride, int plane_index, int pixel_stride) |
... | ... |
@@ -410,68 +315,6 @@ static int encode_plane(FFV1Context *s, uint8_t *src, int w, int h, |
410 | 410 |
return 0; |
411 | 411 |
} |
412 | 412 |
|
413 |
-static int encode_rgb_frame(FFV1Context *s, const uint8_t *src[3], |
|
414 |
- int w, int h, const int stride[3]) |
|
415 |
-{ |
|
416 |
- int x, y, p, i; |
|
417 |
- const int ring_size = s->context_model ? 3 : 2; |
|
418 |
- int16_t *sample[4][3]; |
|
419 |
- int lbd = s->bits_per_raw_sample <= 8; |
|
420 |
- int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; |
|
421 |
- int offset = 1 << bits; |
|
422 |
- |
|
423 |
- s->run_index = 0; |
|
424 |
- |
|
425 |
- memset(s->sample_buffer, 0, ring_size * MAX_PLANES * |
|
426 |
- (w + 6) * sizeof(*s->sample_buffer)); |
|
427 |
- |
|
428 |
- for (y = 0; y < h; y++) { |
|
429 |
- for (i = 0; i < ring_size; i++) |
|
430 |
- for (p = 0; p < MAX_PLANES; p++) |
|
431 |
- sample[p][i]= s->sample_buffer + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3; |
|
432 |
- |
|
433 |
- for (x = 0; x < w; x++) { |
|
434 |
- int b, g, r, av_uninit(a); |
|
435 |
- if (lbd) { |
|
436 |
- unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y)); |
|
437 |
- b = v & 0xFF; |
|
438 |
- g = (v >> 8) & 0xFF; |
|
439 |
- r = (v >> 16) & 0xFF; |
|
440 |
- a = v >> 24; |
|
441 |
- } else { |
|
442 |
- b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); |
|
443 |
- g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); |
|
444 |
- r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); |
|
445 |
- } |
|
446 |
- |
|
447 |
- if (s->slice_coding_mode != 1) { |
|
448 |
- b -= g; |
|
449 |
- r -= g; |
|
450 |
- g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; |
|
451 |
- b += offset; |
|
452 |
- r += offset; |
|
453 |
- } |
|
454 |
- |
|
455 |
- sample[0][0][x] = g; |
|
456 |
- sample[1][0][x] = b; |
|
457 |
- sample[2][0][x] = r; |
|
458 |
- sample[3][0][x] = a; |
|
459 |
- } |
|
460 |
- for (p = 0; p < 3 + s->transparency; p++) { |
|
461 |
- int ret; |
|
462 |
- sample[p][0][-1] = sample[p][1][0 ]; |
|
463 |
- sample[p][1][ w] = sample[p][1][w-1]; |
|
464 |
- if (lbd && s->slice_coding_mode == 0) |
|
465 |
- ret = encode_line(s, w, sample[p], (p + 1) / 2, 9); |
|
466 |
- else |
|
467 |
- ret = encode_line(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1)); |
|
468 |
- if (ret < 0) |
|
469 |
- return ret; |
|
470 |
- } |
|
471 |
- } |
|
472 |
- return 0; |
|
473 |
-} |
|
474 |
- |
|
475 | 413 |
static void write_quant_table(RangeCoder *c, int16_t *quant_table) |
476 | 414 |
{ |
477 | 415 |
int last = 0; |
478 | 416 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,186 @@ |
0 |
+/* |
|
1 |
+ * FFV1 encoder template |
|
2 |
+ * |
|
3 |
+ * Copyright (c) 2003-2016 Michael Niedermayer <michaelni@gmx.at> |
|
4 |
+ * |
|
5 |
+ * This file is part of FFmpeg. |
|
6 |
+ * |
|
7 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
8 |
+ * modify it under the terms of the GNU Lesser General Public |
|
9 |
+ * License as published by the Free Software Foundation; either |
|
10 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
11 |
+ * |
|
12 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
13 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 |
+ * Lesser General Public License for more details. |
|
16 |
+ * |
|
17 |
+ * You should have received a copy of the GNU Lesser General Public |
|
18 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
19 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
20 |
+ */ |
|
21 |
+ |
|
22 |
+static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w, |
|
23 |
+ TYPE *sample[3], |
|
24 |
+ int plane_index, int bits) |
|
25 |
+{ |
|
26 |
+ PlaneContext *const p = &s->plane[plane_index]; |
|
27 |
+ RangeCoder *const c = &s->c; |
|
28 |
+ int x; |
|
29 |
+ int run_index = s->run_index; |
|
30 |
+ int run_count = 0; |
|
31 |
+ int run_mode = 0; |
|
32 |
+ |
|
33 |
+ if (s->ac != AC_GOLOMB_RICE) { |
|
34 |
+ if (c->bytestream_end - c->bytestream < w * 35) { |
|
35 |
+ av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
|
36 |
+ return AVERROR_INVALIDDATA; |
|
37 |
+ } |
|
38 |
+ } else { |
|
39 |
+ if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < w * 4) { |
|
40 |
+ av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); |
|
41 |
+ return AVERROR_INVALIDDATA; |
|
42 |
+ } |
|
43 |
+ } |
|
44 |
+ |
|
45 |
+ if (s->slice_coding_mode == 1) { |
|
46 |
+ for (x = 0; x < w; x++) { |
|
47 |
+ int i; |
|
48 |
+ int v = sample[0][x]; |
|
49 |
+ for (i = bits-1; i>=0; i--) { |
|
50 |
+ uint8_t state = 128; |
|
51 |
+ put_rac(c, &state, (v>>i) & 1); |
|
52 |
+ } |
|
53 |
+ } |
|
54 |
+ return 0; |
|
55 |
+ } |
|
56 |
+ |
|
57 |
+ for (x = 0; x < w; x++) { |
|
58 |
+ int diff, context; |
|
59 |
+ |
|
60 |
+ context = RENAME(get_context)(p, sample[0] + x, sample[1] + x, sample[2] + x); |
|
61 |
+ diff = sample[0][x] - RENAME(predict)(sample[0] + x, sample[1] + x); |
|
62 |
+ |
|
63 |
+ if (context < 0) { |
|
64 |
+ context = -context; |
|
65 |
+ diff = -diff; |
|
66 |
+ } |
|
67 |
+ |
|
68 |
+ diff = fold(diff, bits); |
|
69 |
+ |
|
70 |
+ if (s->ac != AC_GOLOMB_RICE) { |
|
71 |
+ if (s->flags & AV_CODEC_FLAG_PASS1) { |
|
72 |
+ put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, |
|
73 |
+ s->rc_stat2[p->quant_table_index][context]); |
|
74 |
+ } else { |
|
75 |
+ put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL); |
|
76 |
+ } |
|
77 |
+ } else { |
|
78 |
+ if (context == 0) |
|
79 |
+ run_mode = 1; |
|
80 |
+ |
|
81 |
+ if (run_mode) { |
|
82 |
+ if (diff) { |
|
83 |
+ while (run_count >= 1 << ff_log2_run[run_index]) { |
|
84 |
+ run_count -= 1 << ff_log2_run[run_index]; |
|
85 |
+ run_index++; |
|
86 |
+ put_bits(&s->pb, 1, 1); |
|
87 |
+ } |
|
88 |
+ |
|
89 |
+ put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count); |
|
90 |
+ if (run_index) |
|
91 |
+ run_index--; |
|
92 |
+ run_count = 0; |
|
93 |
+ run_mode = 0; |
|
94 |
+ if (diff > 0) |
|
95 |
+ diff--; |
|
96 |
+ } else { |
|
97 |
+ run_count++; |
|
98 |
+ } |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", |
|
102 |
+ run_count, run_index, run_mode, x, |
|
103 |
+ (int)put_bits_count(&s->pb)); |
|
104 |
+ |
|
105 |
+ if (run_mode == 0) |
|
106 |
+ put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits); |
|
107 |
+ } |
|
108 |
+ } |
|
109 |
+ if (run_mode) { |
|
110 |
+ while (run_count >= 1 << ff_log2_run[run_index]) { |
|
111 |
+ run_count -= 1 << ff_log2_run[run_index]; |
|
112 |
+ run_index++; |
|
113 |
+ put_bits(&s->pb, 1, 1); |
|
114 |
+ } |
|
115 |
+ |
|
116 |
+ if (run_count) |
|
117 |
+ put_bits(&s->pb, 1, 1); |
|
118 |
+ } |
|
119 |
+ s->run_index = run_index; |
|
120 |
+ |
|
121 |
+ return 0; |
|
122 |
+} |
|
123 |
+ |
|
124 |
+static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], |
|
125 |
+ int w, int h, const int stride[3]) |
|
126 |
+{ |
|
127 |
+ int x, y, p, i; |
|
128 |
+ const int ring_size = s->context_model ? 3 : 2; |
|
129 |
+ TYPE *sample[4][3]; |
|
130 |
+ int lbd = s->bits_per_raw_sample <= 8; |
|
131 |
+ int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; |
|
132 |
+ int offset = 1 << bits; |
|
133 |
+ |
|
134 |
+ s->run_index = 0; |
|
135 |
+ |
|
136 |
+ memset(RENAME(s->sample_buffer), 0, ring_size * MAX_PLANES * |
|
137 |
+ (w + 6) * sizeof(*RENAME(s->sample_buffer))); |
|
138 |
+ |
|
139 |
+ for (y = 0; y < h; y++) { |
|
140 |
+ for (i = 0; i < ring_size; i++) |
|
141 |
+ for (p = 0; p < MAX_PLANES; p++) |
|
142 |
+ sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3; |
|
143 |
+ |
|
144 |
+ for (x = 0; x < w; x++) { |
|
145 |
+ int b, g, r, av_uninit(a); |
|
146 |
+ if (lbd) { |
|
147 |
+ unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y)); |
|
148 |
+ b = v & 0xFF; |
|
149 |
+ g = (v >> 8) & 0xFF; |
|
150 |
+ r = (v >> 16) & 0xFF; |
|
151 |
+ a = v >> 24; |
|
152 |
+ } else { |
|
153 |
+ b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); |
|
154 |
+ g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); |
|
155 |
+ r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); |
|
156 |
+ } |
|
157 |
+ |
|
158 |
+ if (s->slice_coding_mode != 1) { |
|
159 |
+ b -= g; |
|
160 |
+ r -= g; |
|
161 |
+ g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; |
|
162 |
+ b += offset; |
|
163 |
+ r += offset; |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ sample[0][0][x] = g; |
|
167 |
+ sample[1][0][x] = b; |
|
168 |
+ sample[2][0][x] = r; |
|
169 |
+ sample[3][0][x] = a; |
|
170 |
+ } |
|
171 |
+ for (p = 0; p < 3 + s->transparency; p++) { |
|
172 |
+ int ret; |
|
173 |
+ sample[p][0][-1] = sample[p][1][0 ]; |
|
174 |
+ sample[p][1][ w] = sample[p][1][w-1]; |
|
175 |
+ if (lbd && s->slice_coding_mode == 0) |
|
176 |
+ ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, 9); |
|
177 |
+ else |
|
178 |
+ ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1)); |
|
179 |
+ if (ret < 0) |
|
180 |
+ return ret; |
|
181 |
+ } |
|
182 |
+ } |
|
183 |
+ return 0; |
|
184 |
+} |
|
185 |
+ |