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