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