Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Lagarith lossless decoder | ||
3 | * Copyright (c) 2009 Nathan Caldwell <saintdev (at) gmail.com> | ||
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 | /** | ||
23 | * @file | ||
24 | * Lagarith lossless decoder | ||
25 | * @author Nathan Caldwell | ||
26 | */ | ||
27 | |||
28 | #include <inttypes.h> | ||
29 | |||
30 | #include "avcodec.h" | ||
31 | #include "codec_internal.h" | ||
32 | #include "get_bits.h" | ||
33 | #include "mathops.h" | ||
34 | #include "lagarithrac.h" | ||
35 | #include "lossless_videodsp.h" | ||
36 | #include "thread.h" | ||
37 | |||
38 | enum LagarithFrameType { | ||
39 | FRAME_RAW = 1, /**< uncompressed */ | ||
40 | FRAME_U_RGB24 = 2, /**< unaligned RGB24 */ | ||
41 | FRAME_ARITH_YUY2 = 3, /**< arithmetic coded YUY2 */ | ||
42 | FRAME_ARITH_RGB24 = 4, /**< arithmetic coded RGB24 */ | ||
43 | FRAME_SOLID_GRAY = 5, /**< solid grayscale color frame */ | ||
44 | FRAME_SOLID_COLOR = 6, /**< solid non-grayscale color frame */ | ||
45 | FRAME_OLD_ARITH_RGB = 7, /**< obsolete arithmetic coded RGB (no longer encoded by upstream since version 1.1.0) */ | ||
46 | FRAME_ARITH_RGBA = 8, /**< arithmetic coded RGBA */ | ||
47 | FRAME_SOLID_RGBA = 9, /**< solid RGBA color frame */ | ||
48 | FRAME_ARITH_YV12 = 10, /**< arithmetic coded YV12 */ | ||
49 | FRAME_REDUCED_RES = 11, /**< reduced resolution YV12 frame */ | ||
50 | }; | ||
51 | |||
52 | typedef struct LagarithContext { | ||
53 | AVCodecContext *avctx; | ||
54 | LLVidDSPContext llviddsp; | ||
55 | int zeros; /**< number of consecutive zero bytes encountered */ | ||
56 | int zeros_rem; /**< number of zero bytes remaining to output */ | ||
57 | } LagarithContext; | ||
58 | |||
59 | /** | ||
60 | * Compute the 52-bit mantissa of 1/(double)denom. | ||
61 | * This crazy format uses floats in an entropy coder and we have to match x86 | ||
62 | * rounding exactly, thus ordinary floats aren't portable enough. | ||
63 | * @param denom denominator | ||
64 | * @return 52-bit mantissa | ||
65 | * @see softfloat_mul | ||
66 | */ | ||
67 | 124 | static uint64_t softfloat_reciprocal(uint32_t denom) | |
68 | { | ||
69 | 124 | int shift = av_log2(denom - 1) + 1; | |
70 | 124 | uint64_t ret = (1ULL << 52) / denom; | |
71 | 124 | uint64_t err = (1ULL << 52) - ret * denom; | |
72 | 124 | ret <<= shift; | |
73 | 124 | err <<= shift; | |
74 | 124 | err += denom / 2; | |
75 | 124 | return ret + err / denom; | |
76 | } | ||
77 | |||
78 | /** | ||
79 | * (uint32_t)(x*f), where f has the given mantissa, and exponent 0 | ||
80 | * Used in combination with softfloat_reciprocal computes x/(double)denom. | ||
81 | * @param x 32-bit integer factor | ||
82 | * @param mantissa mantissa of f with exponent 0 | ||
83 | * @return 32-bit integer value (x*f) | ||
84 | * @see softfloat_reciprocal | ||
85 | */ | ||
86 | 31744 | static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa) | |
87 | { | ||
88 | 31744 | uint64_t l = x * (mantissa & 0xffffffff); | |
89 | 31744 | uint64_t h = x * (mantissa >> 32); | |
90 | 31744 | h += l >> 32; | |
91 | 31744 | l &= 0xffffffff; | |
92 | 31744 | l += 1LL << av_log2(h >> 21); | |
93 | 31744 | h += l >> 32; | |
94 | 31744 | return h >> 20; | |
95 | } | ||
96 | |||
97 | 462516 | static uint8_t lag_calc_zero_run(int8_t x) | |
98 | { | ||
99 | 462516 | return (x * 2) ^ (x >> 7); | |
100 | } | ||
101 | |||
102 | 21140 | static int lag_decode_prob(GetBitContext *gb, uint32_t *value) | |
103 | { | ||
104 | static const uint8_t series[] = { 1, 2, 3, 5, 8, 13, 21 }; | ||
105 | int i; | ||
106 | 21140 | int bit = 0; | |
107 | 21140 | int bits = 0; | |
108 | 21140 | int prevbit = 0; | |
109 | unsigned val; | ||
110 | |||
111 |
2/2✓ Branch 0 taken 97888 times.
✓ Branch 1 taken 102 times.
|
97990 | for (i = 0; i < 7; i++) { |
112 |
4/4✓ Branch 0 taken 26483 times.
✓ Branch 1 taken 71405 times.
✓ Branch 2 taken 21038 times.
✓ Branch 3 taken 5445 times.
|
97888 | if (prevbit && bit) |
113 | 21038 | break; | |
114 | 76850 | prevbit = bit; | |
115 | 76850 | bit = get_bits1(gb); | |
116 |
4/4✓ Branch 0 taken 47725 times.
✓ Branch 1 taken 29125 times.
✓ Branch 2 taken 26585 times.
✓ Branch 3 taken 21140 times.
|
76850 | if (bit && !prevbit) |
117 | 26585 | bits += series[i]; | |
118 | } | ||
119 | 21140 | bits--; | |
120 |
2/4✓ Branch 0 taken 21140 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 21140 times.
|
21140 | if (bits < 0 || bits > 31) { |
121 | ✗ | *value = 0; | |
122 | ✗ | return AVERROR_INVALIDDATA; | |
123 |
2/2✓ Branch 0 taken 3841 times.
✓ Branch 1 taken 17299 times.
|
21140 | } else if (bits == 0) { |
124 | 3841 | *value = 0; | |
125 | 3841 | return 0; | |
126 | } | ||
127 | |||
128 | 17299 | val = get_bits_long(gb, bits); | |
129 | 17299 | val |= 1U << bits; | |
130 | |||
131 | 17299 | *value = val - 1; | |
132 | |||
133 | 17299 | return 0; | |
134 | } | ||
135 | |||
136 | 126 | static int lag_read_prob_header(lag_rac *rac, GetBitContext *gb) | |
137 | { | ||
138 | int i, j, scale_factor; | ||
139 | unsigned prob, cumulative_target; | ||
140 | 126 | unsigned cumul_prob = 0; | |
141 | 126 | unsigned scaled_cumul_prob = 0; | |
142 | 126 | int nnz = 0; | |
143 | |||
144 | 126 | rac->prob[0] = 0; | |
145 | 126 | rac->prob[257] = UINT_MAX; | |
146 | /* Read probabilities from bitstream */ | ||
147 |
2/2✓ Branch 0 taken 18484 times.
✓ Branch 1 taken 126 times.
|
18610 | for (i = 1; i < 257; i++) { |
148 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 18484 times.
|
18484 | if (lag_decode_prob(gb, &rac->prob[i]) < 0) { |
149 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability encountered.\n"); | |
150 | ✗ | return AVERROR_INVALIDDATA; | |
151 | } | ||
152 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18484 times.
|
18484 | if ((uint64_t)cumul_prob + rac->prob[i] > UINT_MAX) { |
153 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, "Integer overflow encountered in cumulative probability calculation.\n"); | |
154 | ✗ | return AVERROR_INVALIDDATA; | |
155 | } | ||
156 | 18484 | cumul_prob += rac->prob[i]; | |
157 |
2/2✓ Branch 0 taken 2656 times.
✓ Branch 1 taken 15828 times.
|
18484 | if (!rac->prob[i]) { |
158 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2656 times.
|
2656 | if (lag_decode_prob(gb, &prob)) { |
159 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability run encountered.\n"); | |
160 | ✗ | return AVERROR_INVALIDDATA; | |
161 | } | ||
162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2656 times.
|
2656 | if (prob > 256 - i) |
163 | ✗ | prob = 256 - i; | |
164 |
2/2✓ Branch 0 taken 13772 times.
✓ Branch 1 taken 2656 times.
|
16428 | for (j = 0; j < prob; j++) |
165 | 13772 | rac->prob[++i] = 0; | |
166 | }else { | ||
167 | 15828 | nnz++; | |
168 | } | ||
169 | } | ||
170 | |||
171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | if (!cumul_prob) { |
172 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, "All probabilities are 0!\n"); | |
173 | ✗ | return AVERROR_INVALIDDATA; | |
174 | } | ||
175 | |||
176 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
126 | if (nnz == 1 && (show_bits_long(gb, 32) & 0xFFFFFF)) { |
177 | ✗ | return AVERROR_INVALIDDATA; | |
178 | } | ||
179 | |||
180 | /* Scale probabilities so cumulative probability is an even power of 2. */ | ||
181 | 126 | scale_factor = av_log2(cumul_prob); | |
182 | |||
183 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 2 times.
|
126 | if (cumul_prob & (cumul_prob - 1)) { |
184 | 124 | uint64_t mul = softfloat_reciprocal(cumul_prob); | |
185 |
2/2✓ Branch 0 taken 15872 times.
✓ Branch 1 taken 124 times.
|
15996 | for (i = 1; i <= 128; i++) { |
186 | 15872 | rac->prob[i] = softfloat_mul(rac->prob[i], mul); | |
187 | 15872 | scaled_cumul_prob += rac->prob[i]; | |
188 | } | ||
189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
|
124 | if (scaled_cumul_prob <= 0) { |
190 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, "Scaled probabilities invalid\n"); | |
191 | ✗ | return AVERROR_INVALIDDATA; | |
192 | } | ||
193 |
2/2✓ Branch 0 taken 15872 times.
✓ Branch 1 taken 124 times.
|
15996 | for (; i < 257; i++) { |
194 | 15872 | rac->prob[i] = softfloat_mul(rac->prob[i], mul); | |
195 | 15872 | scaled_cumul_prob += rac->prob[i]; | |
196 | } | ||
197 | |||
198 | 124 | scale_factor++; | |
199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
|
124 | if (scale_factor >= 32U) |
200 | ✗ | return AVERROR_INVALIDDATA; | |
201 | 124 | cumulative_target = 1U << scale_factor; | |
202 | |||
203 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
|
124 | if (scaled_cumul_prob > cumulative_target) { |
204 | ✗ | av_log(rac->avctx, AV_LOG_ERROR, | |
205 | "Scaled probabilities are larger than target!\n"); | ||
206 | ✗ | return AVERROR_INVALIDDATA; | |
207 | } | ||
208 | |||
209 | 124 | scaled_cumul_prob = cumulative_target - scaled_cumul_prob; | |
210 | |||
211 |
2/2✓ Branch 0 taken 12751 times.
✓ Branch 1 taken 124 times.
|
12875 | for (i = 1; scaled_cumul_prob; i = (i & 0x7f) + 1) { |
212 |
2/2✓ Branch 0 taken 7341 times.
✓ Branch 1 taken 5410 times.
|
12751 | if (rac->prob[i]) { |
213 | 7341 | rac->prob[i]++; | |
214 | 7341 | scaled_cumul_prob--; | |
215 | } | ||
216 | /* Comment from reference source: | ||
217 | * if (b & 0x80 == 0) { // order of operations is 'wrong'; it has been left this way | ||
218 | * // since the compression change is negligible and fixing it | ||
219 | * // breaks backwards compatibility | ||
220 | * b =- (signed int)b; | ||
221 | * b &= 0xFF; | ||
222 | * } else { | ||
223 | * b++; | ||
224 | * b &= 0x7f; | ||
225 | * } | ||
226 | */ | ||
227 | } | ||
228 | } | ||
229 | |||
230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | if (scale_factor > 23) |
231 | ✗ | return AVERROR_INVALIDDATA; | |
232 | |||
233 | 126 | rac->scale = scale_factor; | |
234 | |||
235 | /* Fill probability array with cumulative probability for each symbol. */ | ||
236 |
2/2✓ Branch 0 taken 32256 times.
✓ Branch 1 taken 126 times.
|
32382 | for (i = 1; i < 257; i++) |
237 | 32256 | rac->prob[i] += rac->prob[i - 1]; | |
238 | |||
239 | 126 | return 0; | |
240 | } | ||
241 | |||
242 | 49320 | static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1, | |
243 | uint8_t *diff, int w, int *left, | ||
244 | int *left_top) | ||
245 | { | ||
246 | /* This is almost identical to add_hfyu_median_pred in huffyuvdsp.h. | ||
247 | * However the &0xFF on the gradient predictor yields incorrect output | ||
248 | * for lagarith. | ||
249 | */ | ||
250 | int i; | ||
251 | uint8_t l, lt; | ||
252 | |||
253 | 49320 | l = *left; | |
254 | 49320 | lt = *left_top; | |
255 | |||
256 |
2/2✓ Branch 0 taken 33377504 times.
✓ Branch 1 taken 49320 times.
|
33426824 | for (i = 0; i < w; i++) { |
257 | 33377504 | l = mid_pred(l, src1[i], l + src1[i] - lt) + diff[i]; | |
258 | 33377504 | lt = src1[i]; | |
259 | 33377504 | dst[i] = l; | |
260 | } | ||
261 | |||
262 | 49320 | *left = l; | |
263 | 49320 | *left_top = lt; | |
264 | 49320 | } | |
265 | |||
266 | 49440 | static void lag_pred_line(LagarithContext *l, uint8_t *buf, | |
267 | int width, int stride, int line) | ||
268 | { | ||
269 | int L, TL; | ||
270 | |||
271 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 49320 times.
|
49440 | if (!line) { |
272 | /* Left prediction only for first line */ | ||
273 | 120 | L = l->llviddsp.add_left_pred(buf, buf, width, 0); | |
274 | } else { | ||
275 | /* Left pixel is actually prev_row[width] */ | ||
276 | 49320 | L = buf[width - stride - 1]; | |
277 | |||
278 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 49200 times.
|
49320 | if (line == 1) { |
279 | /* Second line, left predict first pixel, the rest of the line is median predicted | ||
280 | * NOTE: In the case of RGB this pixel is top predicted */ | ||
281 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 111 times.
|
120 | TL = l->avctx->pix_fmt == AV_PIX_FMT_YUV420P ? buf[-stride] : L; |
282 | } else { | ||
283 | /* Top left is 2 rows back, last pixel */ | ||
284 | 49200 | TL = buf[width - (2 * stride) - 1]; | |
285 | } | ||
286 | |||
287 | 49320 | add_lag_median_prediction(buf, buf - stride, buf, | |
288 | width, &L, &TL); | ||
289 | } | ||
290 | 49440 | } | |
291 | |||
292 | 4608 | static void lag_pred_line_yuy2(LagarithContext *l, uint8_t *buf, | |
293 | int width, int stride, int line, | ||
294 | int is_luma) | ||
295 | { | ||
296 | int L, TL; | ||
297 | |||
298 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4602 times.
|
4608 | if (!line) { |
299 | 6 | L= buf[0]; | |
300 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (is_luma) |
301 | 2 | buf[0] = 0; | |
302 | 6 | l->llviddsp.add_left_pred(buf, buf, width, 0); | |
303 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (is_luma) |
304 | 2 | buf[0] = L; | |
305 | 6 | return; | |
306 | } | ||
307 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4596 times.
|
4602 | if (line == 1) { |
308 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | const int HEAD = is_luma ? 4 : 2; |
309 | int i; | ||
310 | |||
311 | 6 | L = buf[width - stride - 1]; | |
312 | 6 | TL = buf[HEAD - stride - 1]; | |
313 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 6 times.
|
22 | for (i = 0; i < HEAD; i++) { |
314 | 16 | L += buf[i]; | |
315 | 16 | buf[i] = L; | |
316 | } | ||
317 |
2/2✓ Branch 0 taken 4080 times.
✓ Branch 1 taken 6 times.
|
4086 | for (; i < width; i++) { |
318 | 4080 | L = mid_pred(L & 0xFF, buf[i - stride], (L + buf[i - stride] - TL) & 0xFF) + buf[i]; | |
319 | 4080 | TL = buf[i - stride]; | |
320 | 4080 | buf[i] = L; | |
321 | } | ||
322 | } else { | ||
323 | 4596 | TL = buf[width - (2 * stride) - 1]; | |
324 | 4596 | L = buf[width - stride - 1]; | |
325 | 4596 | l->llviddsp.add_median_pred(buf, buf - stride, buf, width, &L, &TL); | |
326 | } | ||
327 | } | ||
328 | |||
329 | 54048 | static int lag_decode_line(LagarithContext *l, lag_rac *rac, | |
330 | uint8_t *dst, int width, int stride, | ||
331 | int esc_count) | ||
332 | { | ||
333 | 54048 | int i = 0; | |
334 | 54048 | int ret = 0; | |
335 | |||
336 |
2/2✓ Branch 0 taken 52392 times.
✓ Branch 1 taken 1656 times.
|
54048 | if (!esc_count) |
337 | 1656 | esc_count = -1; | |
338 | |||
339 | /* Output any zeros remaining from the previous run */ | ||
340 | 54048 | handle_zeros: | |
341 |
2/2✓ Branch 0 taken 376521 times.
✓ Branch 1 taken 140043 times.
|
516564 | if (l->zeros_rem) { |
342 | 376521 | int count = FFMIN(l->zeros_rem, width - i); | |
343 | 376521 | memset(dst + i, 0, count); | |
344 | 376521 | i += count; | |
345 | 376521 | l->zeros_rem -= count; | |
346 | } | ||
347 | |||
348 |
2/2✓ Branch 0 taken 4147575 times.
✓ Branch 1 taken 54048 times.
|
4201623 | while (i < width) { |
349 | 4147575 | dst[i] = lag_get_rac(rac); | |
350 | 4147575 | ret++; | |
351 | |||
352 |
2/2✓ Branch 0 taken 2802454 times.
✓ Branch 1 taken 1345121 times.
|
4147575 | if (dst[i]) |
353 | 2802454 | l->zeros = 0; | |
354 | else | ||
355 | 1345121 | l->zeros++; | |
356 | |||
357 | 4147575 | i++; | |
358 |
2/2✓ Branch 0 taken 462516 times.
✓ Branch 1 taken 3685059 times.
|
4147575 | if (l->zeros == esc_count) { |
359 | 462516 | int index = lag_get_rac(rac); | |
360 | 462516 | ret++; | |
361 | |||
362 | 462516 | l->zeros = 0; | |
363 | |||
364 | 462516 | l->zeros_rem = lag_calc_zero_run(index); | |
365 | 462516 | goto handle_zeros; | |
366 | } | ||
367 | } | ||
368 | 54048 | return ret; | |
369 | } | ||
370 | |||
371 | ✗ | static int lag_decode_zero_run_line(LagarithContext *l, uint8_t *dst, | |
372 | const uint8_t *src, const uint8_t *src_end, | ||
373 | int width, int esc_count) | ||
374 | { | ||
375 | ✗ | int i = 0; | |
376 | int count; | ||
377 | ✗ | uint8_t zero_run = 0; | |
378 | ✗ | const uint8_t *src_start = src; | |
379 | ✗ | uint8_t mask1 = -(esc_count < 2); | |
380 | ✗ | uint8_t mask2 = -(esc_count < 3); | |
381 | ✗ | uint8_t *end = dst + (width - 2); | |
382 | |||
383 | ✗ | avpriv_request_sample(l->avctx, "zero_run_line"); | |
384 | |||
385 | ✗ | memset(dst, 0, width); | |
386 | |||
387 | ✗ | output_zeros: | |
388 | ✗ | if (l->zeros_rem) { | |
389 | ✗ | count = FFMIN(l->zeros_rem, width - i); | |
390 | ✗ | if (end - dst < count) { | |
391 | ✗ | av_log(l->avctx, AV_LOG_ERROR, "Too many zeros remaining.\n"); | |
392 | ✗ | return AVERROR_INVALIDDATA; | |
393 | } | ||
394 | |||
395 | ✗ | memset(dst, 0, count); | |
396 | ✗ | l->zeros_rem -= count; | |
397 | ✗ | dst += count; | |
398 | } | ||
399 | |||
400 | ✗ | while (dst < end) { | |
401 | ✗ | i = 0; | |
402 | ✗ | while (!zero_run && dst + i < end) { | |
403 | ✗ | i++; | |
404 | ✗ | if (i+2 >= src_end - src) | |
405 | ✗ | return AVERROR_INVALIDDATA; | |
406 | ✗ | zero_run = | |
407 | ✗ | !(src[i] | (src[i + 1] & mask1) | (src[i + 2] & mask2)); | |
408 | } | ||
409 | ✗ | if (zero_run) { | |
410 | ✗ | zero_run = 0; | |
411 | ✗ | i += esc_count; | |
412 | ✗ | if (i > end - dst || | |
413 | ✗ | i >= src_end - src) | |
414 | ✗ | return AVERROR_INVALIDDATA; | |
415 | ✗ | memcpy(dst, src, i); | |
416 | ✗ | dst += i; | |
417 | ✗ | l->zeros_rem = lag_calc_zero_run(src[i]); | |
418 | |||
419 | ✗ | src += i + 1; | |
420 | ✗ | goto output_zeros; | |
421 | } else { | ||
422 | ✗ | memcpy(dst, src, i); | |
423 | ✗ | src += i; | |
424 | ✗ | dst += i; | |
425 | } | ||
426 | } | ||
427 | ✗ | return src - src_start; | |
428 | } | ||
429 | |||
430 | |||
431 | |||
432 | 134 | static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst, | |
433 | int width, int height, int stride, | ||
434 | const uint8_t *src, int src_size) | ||
435 | { | ||
436 | 134 | int i = 0; | |
437 | 134 | int read = 0; | |
438 | uint32_t length; | ||
439 | 134 | uint32_t offset = 1; | |
440 | int esc_count; | ||
441 | GetBitContext gb; | ||
442 | lag_rac rac; | ||
443 | 134 | const uint8_t *src_end = src + src_size; | |
444 | int ret; | ||
445 | |||
446 | 134 | rac.avctx = l->avctx; | |
447 | 134 | l->zeros = 0; | |
448 | |||
449 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 134 times.
|
134 | if(src_size < 2) |
450 | ✗ | return AVERROR_INVALIDDATA; | |
451 | |||
452 | 134 | esc_count = src[0]; | |
453 |
2/2✓ Branch 0 taken 126 times.
✓ Branch 1 taken 8 times.
|
134 | if (esc_count < 4) { |
454 | 126 | length = width * height; | |
455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | if(src_size < 5) |
456 | ✗ | return AVERROR_INVALIDDATA; | |
457 |
3/4✓ Branch 0 taken 123 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 123 times.
✗ Branch 3 not taken.
|
126 | if (esc_count && AV_RL32(src + 1) < length) { |
458 | 123 | length = AV_RL32(src + 1); | |
459 | 123 | offset += 4; | |
460 | } | ||
461 | |||
462 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
|
126 | if ((ret = init_get_bits8(&gb, src + offset, src_size - offset)) < 0) |
463 | ✗ | return ret; | |
464 | |||
465 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
|
126 | if ((ret = lag_read_prob_header(&rac, &gb)) < 0) |
466 | ✗ | return ret; | |
467 | |||
468 | 126 | ff_lag_rac_init(&rac, &gb, length - stride); | |
469 |
2/2✓ Branch 0 taken 54048 times.
✓ Branch 1 taken 126 times.
|
54174 | for (i = 0; i < height; i++) { |
470 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54048 times.
|
54048 | if (rac.overread > MAX_OVERREAD) |
471 | ✗ | return AVERROR_INVALIDDATA; | |
472 | 54048 | read += lag_decode_line(l, &rac, dst + (i * stride), width, | |
473 | stride, esc_count); | ||
474 | } | ||
475 | |||
476 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 126 times.
|
126 | if (read > length) |
477 | ✗ | av_log(l->avctx, AV_LOG_WARNING, | |
478 | "Output more bytes than length (%d of %"PRIu32")\n", read, | ||
479 | length); | ||
480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | } else if (esc_count < 8) { |
481 | ✗ | esc_count -= 4; | |
482 | ✗ | src ++; | |
483 | ✗ | src_size --; | |
484 | ✗ | if (esc_count > 0) { | |
485 | /* Zero run coding only, no range coding. */ | ||
486 | ✗ | for (i = 0; i < height; i++) { | |
487 | ✗ | int res = lag_decode_zero_run_line(l, dst + (i * stride), src, | |
488 | src_end, width, esc_count); | ||
489 | ✗ | if (res < 0) | |
490 | ✗ | return res; | |
491 | ✗ | src += res; | |
492 | } | ||
493 | } else { | ||
494 | ✗ | if (src_size < width * height) | |
495 | ✗ | return AVERROR_INVALIDDATA; // buffer not big enough | |
496 | /* Plane is stored uncompressed */ | ||
497 | ✗ | for (i = 0; i < height; i++) { | |
498 | ✗ | memcpy(dst + (i * stride), src, width); | |
499 | ✗ | src += width; | |
500 | } | ||
501 | } | ||
502 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | } else if (esc_count == 0xff) { |
503 | /* Plane is a solid run of given value */ | ||
504 |
2/2✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 8 times.
|
2888 | for (i = 0; i < height; i++) |
505 | 2880 | memset(dst + i * stride, src[1], width); | |
506 | /* Do not apply prediction. | ||
507 | Note: memset to 0 above, setting first value to src[1] | ||
508 | and applying prediction gives the same result. */ | ||
509 | 8 | return 0; | |
510 | } else { | ||
511 | ✗ | av_log(l->avctx, AV_LOG_ERROR, | |
512 | "Invalid zero run escape code! (%#x)\n", esc_count); | ||
513 | ✗ | return AVERROR_INVALIDDATA; | |
514 | } | ||
515 | |||
516 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 6 times.
|
126 | if (l->avctx->pix_fmt != AV_PIX_FMT_YUV422P) { |
517 |
2/2✓ Branch 0 taken 49440 times.
✓ Branch 1 taken 120 times.
|
49560 | for (i = 0; i < height; i++) { |
518 | 49440 | lag_pred_line(l, dst, width, stride, i); | |
519 | 49440 | dst += stride; | |
520 | } | ||
521 | } else { | ||
522 |
2/2✓ Branch 0 taken 4608 times.
✓ Branch 1 taken 6 times.
|
4614 | for (i = 0; i < height; i++) { |
523 | 4608 | lag_pred_line_yuy2(l, dst, width, stride, i, | |
524 | 4608 | width == l->avctx->width); | |
525 | 4608 | dst += stride; | |
526 | } | ||
527 | } | ||
528 | |||
529 | 126 | return 0; | |
530 | } | ||
531 | |||
532 | /** | ||
533 | * Decode a frame. | ||
534 | * @param avctx codec context | ||
535 | * @param data output AVFrame | ||
536 | * @param data_size size of output data or 0 if no picture is returned | ||
537 | * @param avpkt input packet | ||
538 | * @return number of consumed bytes on success or negative if decode fails | ||
539 | */ | ||
540 | 78 | static int lag_decode_frame(AVCodecContext *avctx, AVFrame *p, | |
541 | int *got_frame, AVPacket *avpkt) | ||
542 | { | ||
543 | 78 | const uint8_t *buf = avpkt->data; | |
544 | 78 | unsigned int buf_size = avpkt->size; | |
545 | 78 | LagarithContext *l = avctx->priv_data; | |
546 | uint8_t frametype; | ||
547 | 78 | uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9; | |
548 | uint32_t offs[4]; | ||
549 | uint8_t *srcs[4]; | ||
550 | 78 | int i, j, planes = 3; | |
551 | 78 | int ret = 0; | |
552 | |||
553 | 78 | p->flags |= AV_FRAME_FLAG_KEY; | |
554 | 78 | p->pict_type = AV_PICTURE_TYPE_I; | |
555 | |||
556 | 78 | frametype = buf[0]; | |
557 | |||
558 | 78 | offset_gu = AV_RL32(buf + 1); | |
559 | 78 | offset_bv = AV_RL32(buf + 5); | |
560 | |||
561 |
7/8✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
78 | switch (frametype) { |
562 | 6 | case FRAME_SOLID_RGBA: | |
563 | 6 | avctx->pix_fmt = AV_PIX_FMT_GBRAP; | |
564 | 14 | case FRAME_SOLID_GRAY: | |
565 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
|
14 | if (frametype == FRAME_SOLID_GRAY) |
566 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (avctx->bits_per_coded_sample == 24) { |
567 | 8 | avctx->pix_fmt = AV_PIX_FMT_GBRP; | |
568 | } else { | ||
569 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRAP; | |
570 | ✗ | planes = 4; | |
571 | } | ||
572 | |||
573 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
|
14 | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
574 | ✗ | return ret; | |
575 | |||
576 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
14 | if (frametype == FRAME_SOLID_RGBA) { |
577 |
2/2✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 6 times.
|
2886 | for (i = 0; i < avctx->height; i++) { |
578 | 2880 | memset(p->data[0] + i * p->linesize[0], buf[2], avctx->width); | |
579 | 2880 | memset(p->data[1] + i * p->linesize[1], buf[1], avctx->width); | |
580 | 2880 | memset(p->data[2] + i * p->linesize[2], buf[3], avctx->width); | |
581 | 2880 | memset(p->data[3] + i * p->linesize[3], buf[4], avctx->width); | |
582 | } | ||
583 | } else { | ||
584 |
2/2✓ Branch 0 taken 2880 times.
✓ Branch 1 taken 8 times.
|
2888 | for (i = 0; i < avctx->height; i++) { |
585 |
2/2✓ Branch 0 taken 8640 times.
✓ Branch 1 taken 2880 times.
|
11520 | for (j = 0; j < planes; j++) |
586 | 8640 | memset(p->data[j] + i * p->linesize[j], buf[1], avctx->width); | |
587 | } | ||
588 | } | ||
589 | 14 | break; | |
590 | 26 | case FRAME_SOLID_COLOR: | |
591 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | if (avctx->bits_per_coded_sample == 24) { |
592 | 26 | avctx->pix_fmt = AV_PIX_FMT_GBRP; | |
593 | } else { | ||
594 | ✗ | avctx->pix_fmt = AV_PIX_FMT_GBRAP; | |
595 | } | ||
596 | |||
597 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
|
26 | if ((ret = ff_thread_get_buffer(avctx, p,0)) < 0) |
598 | ✗ | return ret; | |
599 | |||
600 |
2/2✓ Branch 0 taken 6240 times.
✓ Branch 1 taken 26 times.
|
6266 | for (i = 0; i < avctx->height; i++) { |
601 | 6240 | memset(p->data[0] + i * p->linesize[0], buf[2], avctx->width); | |
602 | 6240 | memset(p->data[1] + i * p->linesize[1], buf[1], avctx->width); | |
603 | 6240 | memset(p->data[2] + i * p->linesize[2], buf[3], avctx->width); | |
604 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6240 times.
|
6240 | if (avctx->pix_fmt == AV_PIX_FMT_GBRAP) |
605 | ✗ | memset(p->data[3] + i * p->linesize[3], 0xFFu, avctx->width); | |
606 | } | ||
607 | 26 | break; | |
608 | 20 | case FRAME_ARITH_RGBA: | |
609 | 20 | avctx->pix_fmt = AV_PIX_FMT_GBRAP; | |
610 | 20 | planes = 4; | |
611 | 20 | offset_ry += 4; | |
612 | 20 | offs[3] = AV_RL32(buf + 9); | |
613 | 33 | case FRAME_ARITH_RGB24: | |
614 | case FRAME_U_RGB24: | ||
615 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20 times.
|
33 | if (frametype == FRAME_ARITH_RGB24 || frametype == FRAME_U_RGB24) |
616 | 13 | avctx->pix_fmt = AV_PIX_FMT_GBRP; | |
617 | |||
618 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
33 | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
619 | ✗ | return ret; | |
620 | |||
621 | 33 | offs[0] = offset_bv; | |
622 | 33 | offs[1] = offset_gu; | |
623 | 33 | offs[2] = offset_ry; | |
624 | |||
625 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 33 times.
|
152 | for (i = 0; i < planes; i++) |
626 | 119 | srcs[i] = p->data[i] + (avctx->height - 1) * p->linesize[i]; | |
627 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 33 times.
|
152 | for (i = 0; i < planes; i++) |
628 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
|
119 | if (buf_size <= offs[i]) { |
629 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
630 | "Invalid frame offsets\n"); | ||
631 | ✗ | return AVERROR_INVALIDDATA; | |
632 | } | ||
633 | |||
634 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 33 times.
|
152 | for (i = 0; i < planes; i++) { |
635 | 119 | ret = lag_decode_arith_plane(l, srcs[i], | |
636 | avctx->width, avctx->height, | ||
637 | 119 | -p->linesize[i], buf + offs[i], | |
638 | 119 | buf_size - offs[i]); | |
639 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
|
119 | if (ret < 0) |
640 | ✗ | return ret; | |
641 | } | ||
642 |
2/2✓ Branch 0 taken 13760 times.
✓ Branch 1 taken 33 times.
|
13793 | for (i = 0; i < avctx->height; i++) { |
643 | 13760 | l->llviddsp.add_bytes(p->data[0] + i * p->linesize[0], p->data[1] + i * p->linesize[1], avctx->width); | |
644 | 13760 | l->llviddsp.add_bytes(p->data[2] + i * p->linesize[2], p->data[1] + i * p->linesize[1], avctx->width); | |
645 | } | ||
646 | 33 | FFSWAP(uint8_t*, p->data[0], p->data[1]); | |
647 | 33 | FFSWAP(int, p->linesize[0], p->linesize[1]); | |
648 | 33 | FFSWAP(uint8_t*, p->data[2], p->data[1]); | |
649 | 33 | FFSWAP(int, p->linesize[2], p->linesize[1]); | |
650 | 33 | break; | |
651 | 2 | case FRAME_ARITH_YUY2: | |
652 | 2 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; | |
653 | |||
654 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
655 | ✗ | return ret; | |
656 | |||
657 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | if (offset_ry >= buf_size || |
658 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | offset_gu >= buf_size || |
659 | offset_bv >= buf_size) { | ||
660 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
661 | "Invalid frame offsets\n"); | ||
662 | ✗ | return AVERROR_INVALIDDATA; | |
663 | } | ||
664 | |||
665 | 2 | ret = lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height, | |
666 | p->linesize[0], buf + offset_ry, | ||
667 | 2 | buf_size - offset_ry); | |
668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
669 | ✗ | return ret; | |
670 | 2 | ret = lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2, | |
671 | avctx->height, p->linesize[1], | ||
672 | 2 | buf + offset_gu, buf_size - offset_gu); | |
673 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
674 | ✗ | return ret; | |
675 | 2 | ret = lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2, | |
676 | avctx->height, p->linesize[2], | ||
677 | 2 | buf + offset_bv, buf_size - offset_bv); | |
678 | 2 | break; | |
679 | 3 | case FRAME_ARITH_YV12: | |
680 | 3 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
681 | |||
682 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
683 | ✗ | return ret; | |
684 | |||
685 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | if (offset_ry >= buf_size || |
686 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | offset_gu >= buf_size || |
687 | offset_bv >= buf_size) { | ||
688 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
689 | "Invalid frame offsets\n"); | ||
690 | ✗ | return AVERROR_INVALIDDATA; | |
691 | } | ||
692 | |||
693 | 3 | ret = lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height, | |
694 | p->linesize[0], buf + offset_ry, | ||
695 | 3 | buf_size - offset_ry); | |
696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
697 | ✗ | return ret; | |
698 | 3 | ret = lag_decode_arith_plane(l, p->data[2], (avctx->width + 1) / 2, | |
699 | 3 | (avctx->height + 1) / 2, p->linesize[2], | |
700 | 3 | buf + offset_gu, buf_size - offset_gu); | |
701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
702 | ✗ | return ret; | |
703 | 3 | ret = lag_decode_arith_plane(l, p->data[1], (avctx->width + 1) / 2, | |
704 | 3 | (avctx->height + 1) / 2, p->linesize[1], | |
705 | 3 | buf + offset_bv, buf_size - offset_bv); | |
706 | 3 | break; | |
707 | ✗ | default: | |
708 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
709 | "Unsupported Lagarith frame type: %#"PRIx8"\n", frametype); | ||
710 | ✗ | return AVERROR_PATCHWELCOME; | |
711 | } | ||
712 | |||
713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78 times.
|
78 | if (ret < 0) |
714 | ✗ | return ret; | |
715 | |||
716 | 78 | *got_frame = 1; | |
717 | |||
718 | 78 | return buf_size; | |
719 | } | ||
720 | |||
721 | 18 | static av_cold int lag_decode_init(AVCodecContext *avctx) | |
722 | { | ||
723 | 18 | LagarithContext *l = avctx->priv_data; | |
724 | 18 | l->avctx = avctx; | |
725 | |||
726 | 18 | ff_llviddsp_init(&l->llviddsp); | |
727 | |||
728 | 18 | return 0; | |
729 | } | ||
730 | |||
731 | const FFCodec ff_lagarith_decoder = { | ||
732 | .p.name = "lagarith", | ||
733 | CODEC_LONG_NAME("Lagarith lossless"), | ||
734 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
735 | .p.id = AV_CODEC_ID_LAGARITH, | ||
736 | .priv_data_size = sizeof(LagarithContext), | ||
737 | .init = lag_decode_init, | ||
738 | FF_CODEC_DECODE_CB(lag_decode_frame), | ||
739 | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, | ||
740 | }; | ||
741 |