History

Lagarith decoder by Nathan Caldwell, saintdev at gmail

Originally committed as revision 26270 to svn://svn.ffmpeg.org/ffmpeg/trunk

Carl Eugen Hoyos committed 15 years ago

Commit d267b331 parent c392cc09 files · +699 −1Browse files

Unified · Split

9 files
  1. Changelog +1 −0
  2. doc/general.texi +1 −0
  3. libavcodec/Makefile +1 −0
  4. libavcodec/allcodecs.c +1 −0
  5. libavcodec/avcodec.h +2 −1
  6. libavcodec/lagarith.c +518 −0
  7. libavcodec/lagarithrac.c +58 −0
  8. libavcodec/lagarithrac.h +116 −0
  9. libavformat/riff.c +1 −0
Changelog+1−0
@@ -71,6 +71,7 @@ version <next>: · 70 unmodified lines
7171 - FFmpeg metadata format muxer and demuxer
7272 - SubRip (srt) subtitle decoder
7373 - floating-point AC-3 encoder added
74+- Lagarith decoder
7475
7576
7677 version 0.6:
doc/general.texi+1−0
@@ -424,6 +424,7 @@ following image formats are supported: · 423 unmodified lines
424424 @tab Codec used in Worms games.
425425 @item Kega Game Video (KGV1) @tab @tab X
426426 @tab Kega emulator screen capture codec.
427+@item Lagarith @tab @tab X
427428 @item LCL (LossLess Codec Library) MSZH @tab @tab X
428429 @item LCL (LossLess Codec Library) ZLIB @tab E @tab E
429430 @item LOCO @tab @tab X
libavcodec/Makefile+1−0
@@ -185,6 +185,7 @@ OBJS-$(CONFIG_JPEGLS_DECODER) += jpeglsdec.o jpegls.o \ · 184 unmodified lines
185185 OBJS-$(CONFIG_JPEGLS_ENCODER) += jpeglsenc.o jpegls.o
186186 OBJS-$(CONFIG_KGV1_DECODER) += kgv1dec.o
187187 OBJS-$(CONFIG_KMVC_DECODER) += kmvc.o
188+OBJS-$(CONFIG_LAGARITH_DECODER) += lagarith.o lagarithrac.o
188189 OBJS-$(CONFIG_LJPEG_ENCODER) += ljpegenc.o mjpegenc.o mjpeg.o \
189190 mpegvideo_enc.o motion_est.o \
190191 ratecontrol.o mpeg12data.o \
libavcodec/allcodecs.c+1−0
@@ -128,6 +128,7 @@ void avcodec_register_all(void) · 127 unmodified lines
128128 REGISTER_ENCDEC (JPEGLS, jpegls);
129129 REGISTER_DECODER (KGV1, kgv1);
130130 REGISTER_DECODER (KMVC, kmvc);
131+ REGISTER_DECODER (LAGARITH, lagarith);
131132 REGISTER_ENCODER (LJPEG, ljpeg);
132133 REGISTER_DECODER (LOCO, loco);
133134 REGISTER_DECODER (MDEC, mdec);
libavcodec/avcodec.h+2−1
@@ -32,7 +32,7 @@ · 31 unmodified lines
3232 #include "libavutil/cpu.h"
3333
3434 #define LIBAVCODEC_VERSION_MAJOR 52
35−#define LIBAVCODEC_VERSION_MINOR 107
35+#define LIBAVCODEC_VERSION_MINOR 108
3636 #define LIBAVCODEC_VERSION_MICRO 0
3737
3838 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -259,6 +259,7 @@ enum CodecID { · 220 unmodified lines
259259 CODEC_ID_A64_MULTI5,
260260 CODEC_ID_R10K,
261261 CODEC_ID_MXPEG,
262+ CODEC_ID_LAGARITH,
262263
263264 /* various PCM "codecs" */
264265 CODEC_ID_PCM_S16LE= 0x10000,
libavcodec/lagarith.c+518−0
@@ -0,0 +1,518 @@
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 libavcodec/lagarith.c
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+
34+enum LagarithFrameType {
35+ FRAME_RAW = 1, /*!< uncompressed */
36+ FRAME_U_RGB24 = 2, /*!< unaligned RGB24 */
37+ FRAME_ARITH_YUY2 = 3, /*!< arithmetic coded YUY2 */
38+ FRAME_ARITH_RGB24 = 4, /*!< arithmetic coded RGB24 */
39+ FRAME_SOLID_GRAY = 5, /*!< solid grayscale color frame */
40+ FRAME_SOLID_COLOR = 6, /*!< solid non-grayscale color frame */
41+ FRAME_OLD_ARITH_RGB = 7, /*!< obsolete arithmetic coded RGB (no longer encoded by upstream since version 1.1.0) */
42+ FRAME_ARITH_RGBA = 8, /*!< arithmetic coded RGBA */
43+ FRAME_SOLID_RGBA = 9, /*!< solid RGBA color frame */
44+ FRAME_ARITH_YV12 = 10, /*!< arithmetic coded YV12 */
45+ FRAME_REDUCED_RES = 11, /*!< reduced resolution YV12 frame */
46+};
47+
48+typedef struct LagarithContext {
49+ AVCodecContext *avctx;
50+ AVFrame picture;
51+ DSPContext dsp;
52+ int zeros; /*!< number of consecutive zero bytes encountered */
53+ int zeros_rem; /*!< number of zero bytes remaining to output */
54+} LagarithContext;
55+
56+/**
57+ * Compute the 52bit mantissa of 1/(double)denom.
58+ * This crazy format uses floats in an entropy coder and we have to match x86
59+ * rounding exactly, thus ordinary floats aren't portable enough.
60+ * @param denom denominator
61+ * @return 52bit mantissa
62+ * @see softfloat_mul
63+ */
64+static uint64_t softfloat_reciprocal(uint32_t denom)
65+{
66+ int shift = av_log2(denom - 1) + 1;
67+ uint64_t ret = (1ULL << 52) / denom;
68+ uint64_t err = (1ULL << 52) - ret * denom;
69+ ret <<= shift;
70+ err <<= shift;
71+ err += denom / 2;
72+ return ret + err / denom;
73+}
74+
75+/**
76+ * (uint32_t)(x*f), where f has the given mantissa, and exponent 0
77+ * Used in combination with softfloat_reciprocal computes x/(double)denom.
78+ * @param x 32bit integer factor
79+ * @param mantissa mantissa of f with exponent 0
80+ * @return 32bit integer value (x*f)
81+ * @see softfloat_reciprocal
82+ */
83+static uint32_t softfloat_mul(uint32_t x, uint64_t mantissa)
84+{
85+ uint64_t l = x * (mantissa & 0xffffffff);
86+ uint64_t h = x * (mantissa >> 32);
87+ h += l >> 32;
88+ l &= 0xffffffff;
89+ l += 1 << av_log2(h >> 21);
90+ h += l >> 32;
91+ return h >> 20;
92+}
93+
94+static uint8_t lag_calc_zero_run(int8_t x)
95+{
96+ return (x << 1) ^ (x >> 7);
97+}
98+
99+static int lag_decode_prob(GetBitContext *gb, uint32_t *value)
100+{
101+ static const uint8_t series[] = { 1, 2, 3, 5, 8, 13, 21 };
102+ int i;
103+ int bit = 0;
104+ int bits = 0;
105+ int prevbit = 0;
106+ unsigned val;
107+
108+ for (i = 0; i < 7; i++) {
109+ if (prevbit && bit)
110+ break;
111+ prevbit = bit;
112+ bit = get_bits1(gb);
113+ if (bit && !prevbit)
114+ bits += series[i];
115+ }
116+ bits--;
117+ if (bits < 0 || bits > 31) {
118+ *value = 0;
119+ return -1;
120+ } else if (bits == 0) {
121+ *value = 0;
122+ return 0;
123+ }
124+
125+ val = get_bits_long(gb, bits);
126+ val |= 1 << bits;
127+
128+ *value = val - 1;
129+
130+ return 0;
131+}
132+
133+static int lag_read_prob_header(lag_rac *rac, GetBitContext *gb)
134+{
135+ int i, j, scale_factor;
136+ unsigned prob, cumulative_target;
137+ unsigned cumul_prob = 0;
138+ unsigned scaled_cumul_prob = 0;
139+
140+ rac->prob[0] = 0;
141+ rac->prob[257] = UINT_MAX;
142+ /* Read probabilities from bitstream */
143+ for (i = 1; i < 257; i++) {
144+ if (lag_decode_prob(gb, &rac->prob[i]) < 0) {
145+ av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability encountered.\n");
146+ return -1;
147+ }
148+ if ((uint64_t)cumul_prob + rac->prob[i] > UINT_MAX) {
149+ av_log(rac->avctx, AV_LOG_ERROR, "Integer overflow encountered in cumulative probability calculation.\n");
150+ return -1;
151+ }
152+ cumul_prob += rac->prob[i];
153+ if (!rac->prob[i]) {
154+ if (lag_decode_prob(gb, &prob)) {
155+ av_log(rac->avctx, AV_LOG_ERROR, "Invalid probability run encountered.\n");
156+ return -1;
157+ }
158+ if (prob > 257 - i)
159+ prob = 257 - i;
160+ for (j = 0; j < prob; j++)
161+ rac->prob[++i] = 0;
162+ }
163+ }
164+
165+ if (!cumul_prob) {
166+ av_log(rac->avctx, AV_LOG_ERROR, "All probabilities are 0!\n");
167+ return -1;
168+ }
169+
170+ /* Scale probabilities so cumulative probability is an even power of 2. */
171+ scale_factor = av_log2(cumul_prob);
172+
173+ if (cumul_prob & (cumul_prob - 1)) {
174+ uint64_t mul = softfloat_reciprocal(cumul_prob);
175+ for (i = 1; i < 257; i++) {
176+ rac->prob[i] = softfloat_mul(rac->prob[i], mul);
177+ scaled_cumul_prob += rac->prob[i];
178+ }
179+
180+ scale_factor++;
181+ cumulative_target = 1 << scale_factor;
182+
183+ if (scaled_cumul_prob > cumulative_target) {
184+ av_log(rac->avctx, AV_LOG_ERROR,
185+ "Scaled probabilities are larger than target!\n");
186+ return -1;
187+ }
188+
189+ scaled_cumul_prob = cumulative_target - scaled_cumul_prob;
190+
191+ for (i = 1; scaled_cumul_prob; i = (i & 0x7f) + 1) {
192+ if (rac->prob[i]) {
193+ rac->prob[i]++;
194+ scaled_cumul_prob--;
195+ }
196+ /* Comment from reference source:
197+ * if (b & 0x80 == 0) { // order of operations is 'wrong'; it has been left this way
198+ * // since the compression change is negligable and fixing it
199+ * // breaks backwards compatibilty
200+ * b =- (signed int)b;
201+ * b &= 0xFF;
202+ * } else {
203+ * b++;
204+ * b &= 0x7f;
205+ * }
206+ */
207+ }
208+ }
209+
210+ rac->scale = scale_factor;
211+
212+ /* Fill probability array with cumulative probability for each symbol. */
213+ for (i = 1; i < 257; i++)
214+ rac->prob[i] += rac->prob[i - 1];
215+
216+ return 0;
217+}
218+
219+static void add_lag_median_prediction(uint8_t *dst, uint8_t *src1,
220+ uint8_t *diff, int w, int *left,
221+ int *left_top)
222+{
223+ /* This is almost identical to add_hfyu_median_prediction in dsputil.h.
224+ * However the &0xFF on the gradient predictor yealds incorrect output
225+ * for lagarith.
226+ */
227+ int i;
228+ uint8_t l, lt;
229+
230+ l = *left;
231+ lt = *left_top;
232+
233+ for (i = 0; i < w; i++) {
234+ l = mid_pred(l, src1[i], l + src1[i] - lt) + diff[i];
235+ lt = src1[i];
236+ dst[i] = l;
237+ }
238+
239+ *left = l;
240+ *left_top = lt;
241+}
242+
243+static void lag_pred_line(LagarithContext *l, uint8_t *buf,
244+ int width, int stride, int line)
245+{
246+ int L, TL;
247+
248+ if (!line) {
249+ /* Left prediction only for first line */
250+ L = l->dsp.add_hfyu_left_prediction(buf + 1, buf + 1,
251+ width - 1, buf[0]);
252+ return;
253+ } else if (line == 1) {
254+ /* Second line, left predict first pixel, the rest of the line is median predicted */
255+ /* FIXME: In the case of RGB this pixel is top predicted */
256+ TL = buf[-stride];
257+ } else {
258+ /* Top left is 2 rows back, last pixel */
259+ TL = buf[width - (2 * stride) - 1];
260+ }
261+ /* Left pixel is actually prev_row[width] */
262+ L = buf[width - stride - 1];
263+
264+ add_lag_median_prediction(buf, buf - stride, buf,
265+ width, &L, &TL);
266+}
267+
268+static int lag_decode_line(LagarithContext *l, lag_rac *rac,
269+ uint8_t *dst, int width, int stride,
270+ int esc_count)
271+{
272+ int i = 0;
273+ int ret = 0;
274+
275+ if (!esc_count)
276+ esc_count = -1;
277+
278+ /* Output any zeros remaining from the previous run */
279+handle_zeros:
280+ if (l->zeros_rem) {
281+ int count = FFMIN(l->zeros_rem, width - i);
282+ memset(dst + i, 0, count);
283+ i += count;
284+ l->zeros_rem -= count;
285+ }
286+
287+ while (i < width) {
288+ dst[i] = lag_get_rac(rac);
289+ ret++;
290+
291+ if (dst[i])
292+ l->zeros = 0;
293+ else
294+ l->zeros++;
295+
296+ i++;
297+ if (l->zeros == esc_count) {
298+ int index = lag_get_rac(rac);
299+ ret++;
300+
301+ l->zeros = 0;
302+
303+ l->zeros_rem = lag_calc_zero_run(index);
304+ goto handle_zeros;
305+ }
306+ }
307+ return ret;
308+}
309+
310+static int lag_decode_zero_run_line(LagarithContext *l, uint8_t *dst,
311+ const uint8_t *src, int width,
312+ int esc_count)
313+{
314+ int i = 0;
315+ int count;
316+ uint8_t zero_run = 0;
317+ const uint8_t *start = src;
318+ uint8_t mask1 = -(esc_count < 2);
319+ uint8_t mask2 = -(esc_count < 3);
320+ uint8_t *end = dst + (width - 2);
321+
322+output_zeros:
323+ if (l->zeros_rem) {
324+ count = FFMIN(l->zeros_rem, width - i);
325+ memset(dst, 0, count);
326+ l->zeros_rem -= count;
327+ dst += count;
328+ }
329+
330+ while (dst < end) {
331+ i = 0;
332+ while (!zero_run && dst + i < end) {
333+ i++;
334+ zero_run =
335+ !(src[i] | (src[i + 1] & mask1) | (src[i + 2] & mask2));
336+ }
337+ if (zero_run) {
338+ zero_run = 0;
339+ i += esc_count;
340+ memcpy(dst, src, i);
341+ dst += i;
342+ l->zeros_rem = lag_calc_zero_run(src[i]);
343+
344+ src += i + 1;
345+ goto output_zeros;
346+ } else {
347+ memcpy(dst, src, i);
348+ src += i;
349+ }
350+ }
351+ return start - src;
352+}
353+
354+
355+
356+static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst,
357+ int width, int height, int stride,
358+ const uint8_t *src, int src_size)
359+{
360+ int i = 0;
361+ int read = 0;
362+ uint32_t length;
363+ uint32_t offset = 1;
364+ int esc_count = src[0];
365+ GetBitContext gb;
366+ lag_rac rac;
367+
368+ rac.avctx = l->avctx;
369+ l->zeros = 0;
370+
371+ if (esc_count < 4) {
372+ length = width * height;
373+ if (esc_count && AV_RL32(src + 1) < length) {
374+ length = AV_RL32(src + 1);
375+ offset += 4;
376+ }
377+
378+ init_get_bits(&gb, src + offset, src_size * 8);
379+
380+ if (lag_read_prob_header(&rac, &gb) < 0)
381+ return -1;
382+
383+ lag_rac_init(&rac, &gb, length - stride);
384+
385+ for (i = 0; i < height; i++)
386+ read += lag_decode_line(l, &rac, dst + (i * stride), width,
387+ stride, esc_count);
388+
389+ if (read > length)
390+ av_log(l->avctx, AV_LOG_WARNING,
391+ "Output more bytes than length (%d of %d)\n", read,
392+ length);
393+ } else if (esc_count < 8) {
394+ esc_count -= 4;
395+ if (esc_count > 0) {
396+ /* Zero run coding only, no range coding. */
397+ for (i = 0; i < height; i++)
398+ src += lag_decode_zero_run_line(l, dst + (i * stride), src,
399+ width, esc_count);
400+ } else {
401+ /* Plane is stored uncompressed */
402+ for (i = 0; i < height; i++) {
403+ memcpy(dst + (i * stride), src, width);
404+ src += width;
405+ }
406+ }
407+ } else if (esc_count == 0xff) {
408+ /* Plane is a solid run of 0 bytes */
409+ for (i = 0; i < height; i++)
410+ memset(dst + i * stride, 0, width);
411+ } else {
412+ av_log(l->avctx, AV_LOG_ERROR,
413+ "Invalid zero run escape code! (%#x)\n", esc_count);
414+ return -1;
415+ }
416+
417+ for (i = 0; i < height; i++) {
418+ lag_pred_line(l, dst, width, stride, i);
419+ dst += stride;
420+ }
421+
422+ return 0;
423+}
424+
425+/**
426+ * Decode a frame.
427+ * @param avctx codec context
428+ * @param data output AVFrame
429+ * @param data_size size of output data or 0 if no picture is returned
430+ * @param avpkt input packet
431+ * @return number of consumed bytes on success or negative if decode fails
432+ */
433+static int lag_decode_frame(AVCodecContext *avctx,
434+ void *data, int *data_size, AVPacket *avpkt)
435+{
436+ const uint8_t *buf = avpkt->data;
437+ int buf_size = avpkt->size;
438+ LagarithContext *l = avctx->priv_data;
439+ AVFrame *const p = &l->picture;
440+ uint8_t frametype = 0;
441+ uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9;
442+
443+ AVFrame *picture = data;
444+
445+ if (p->data[0])
446+ avctx->release_buffer(avctx, p);
447+
448+ p->reference = 0;
449+ p->key_frame = 1;
450+
451+ frametype = buf[0];
452+
453+ offset_gu = AV_RL32(buf + 1);
454+ offset_bv = AV_RL32(buf + 5);
455+
456+ switch (frametype) {
457+ case FRAME_ARITH_YV12:
458+ avctx->pix_fmt = PIX_FMT_YUV420P;
459+
460+ if (avctx->get_buffer(avctx, p) < 0) {
461+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
462+ return -1;
463+ }
464+
465+ lag_decode_arith_plane(l, p->data[0], avctx->width, avctx->height,
466+ p->linesize[0], buf + offset_ry,
467+ buf_size);
468+ lag_decode_arith_plane(l, p->data[2], avctx->width / 2,
469+ avctx->height / 2, p->linesize[2],
470+ buf + offset_gu, buf_size);
471+ lag_decode_arith_plane(l, p->data[1], avctx->width / 2,
472+ avctx->height / 2, p->linesize[1],
473+ buf + offset_bv, buf_size);
474+ break;
475+ default:
476+ av_log(avctx, AV_LOG_ERROR,
477+ "Unsupported Lagarith frame type: %#x\n", frametype);
478+ return -1;
479+ }
480+
481+ *picture = *p;
482+ *data_size = sizeof(AVFrame);
483+
484+ return buf_size;
485+}
486+
487+static av_cold int lag_decode_init(AVCodecContext *avctx)
488+{
489+ LagarithContext *l = avctx->priv_data;
490+ l->avctx = avctx;
491+
492+ dsputil_init(&l->dsp, avctx);
493+
494+ return 0;
495+}
496+
497+static av_cold int lag_decode_end(AVCodecContext *avctx)
498+{
499+ LagarithContext *l = avctx->priv_data;
500+
501+ if (l->picture.data[0])
502+ avctx->release_buffer(avctx, &l->picture);
503+
504+ return 0;
505+}
506+
507+AVCodec lagarith_decoder = {
508+ "lagarith",
509+ CODEC_TYPE_VIDEO,
510+ CODEC_ID_LAGARITH,
511+ sizeof(LagarithContext),
512+ lag_decode_init,
513+ NULL,
514+ lag_decode_end,
515+ lag_decode_frame,
516+ CODEC_CAP_DR1,
517+ .long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"),
518+};
libavcodec/lagarithrac.c+58−0
@@ -0,0 +1,58 @@
1+/*
2+ * Lagarith range decoder
3+ * Copyright (c) 2009 Nathan Caldwell <saintdev (at) gmail.com>
4+ * Copyright (c) 2009 David Conrad
5+ *
6+ * This file is part of FFmpeg.
7+ *
8+ * FFmpeg is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU Lesser General Public
10+ * License as published by the Free Software Foundation; either
11+ * version 2.1 of the License, or (at your option) any later version.
12+ *
13+ * FFmpeg is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+ * Lesser General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU Lesser General Public
19+ * License along with FFmpeg; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+ */
22+
23+/**
24+ * @file libavcodec/lagarithrac.c
25+ * Lagarith range decoder
26+ * @author Nathan Caldwell
27+ * @author David Conrad
28+ */
29+
30+#include "get_bits.h"
31+#include "lagarithrac.h"
32+
33+void lag_rac_init(lag_rac *l, GetBitContext *gb, int length)
34+{
35+ int i, j;
36+
37+ /* According to reference decoder "1st byte is garbage",
38+ * however, it gets skipped by the call to align_get_bits()
39+ */
40+ align_get_bits(gb);
41+ l->bytestream_start =
42+ l->bytestream = gb->buffer + get_bits_count(gb) / 8;
43+ l->bytestream_end = l->bytestream_start + length;
44+
45+ l->range = 0x80;
46+ l->low = *l->bytestream >> 1;
47+ l->hash_shift = FFMAX(l->scale - 8, 0);
48+
49+ for (i = j = 0; i < 256; i++) {
50+ unsigned r = i << l->hash_shift;
51+ while (l->prob[j + 1] <= r)
52+ j++;
53+ l->range_hash[i] = j;
54+ }
55+
56+ /* Add conversion factor to hash_shift so we don't have to in lag_get_rac. */
57+ l->hash_shift += 23;
58+}
libavcodec/lagarithrac.h+116−0
@@ -0,0 +1,116 @@
1+/*
2+ * Lagarith range decoder
3+ * Copyright (c) 2009 Nathan Caldwell <saintdev (at) gmail.com>
4+ * Copyright (c) 2009 David Conrad
5+ *
6+ * This file is part of FFmpeg.
7+ *
8+ * FFmpeg is free software; you can redistribute it and/or
9+ * modify it under the terms of the GNU Lesser General Public
10+ * License as published by the Free Software Foundation; either
11+ * version 2.1 of the License, or (at your option) any later version.
12+ *
13+ * FFmpeg is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+ * Lesser General Public License for more details.
17+ *
18+ * You should have received a copy of the GNU Lesser General Public
19+ * License along with FFmpeg; if not, write to the Free Software
20+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+ */
22+
23+/**
24+ * @file libavcodec/lagarithrac.h
25+ * Lagarith range decoder
26+ * @author Nathan Caldwell
27+ * @author David Conrad
28+ */
29+
30+#ifndef AVCODEC_LAGARITHRAC_H
31+#define AVCODEC_LAGARITHRAC_H
32+
33+#include <stdint.h>
34+#include "libavutil/common.h"
35+#include "libavutil/intreadwrite.h"
36+#include "avcodec.h"
37+#include "get_bits.h"
38+
39+typedef struct lag_rac {
40+ AVCodecContext *avctx;
41+ unsigned low;
42+ unsigned range;
43+ unsigned scale; /*!< Number of bits of precision in range. */
44+ unsigned hash_shift; /*!< Number of bits to shift to calculate hash for radix search. */
45+
46+ const uint8_t *bytestream_start; /*!< Start of input bytestream. */
47+ const uint8_t *bytestream; /*!< Current position in input bytestream. */
48+ const uint8_t *bytestream_end; /*!< End position of input bytestream. */
49+
50+ uint32_t prob[258]; /*!< Table of cumulative probability for each symbol. */
51+ uint8_t range_hash[256]; /*!< Hash table mapping upper byte to approximate symbol. */
52+} lag_rac;
53+
54+void lag_rac_init(lag_rac *l, GetBitContext *gb, int length);
55+
56+/* TODO: Optimize */
57+static inline void lag_rac_refill(lag_rac *l)
58+{
59+ while (l->range <= 0x800000) {
60+ l->low <<= 8;
61+ l->range <<= 8;
62+ l->low |= 0xff & (AV_RB16(l->bytestream) >> 1);
63+ if (l->bytestream < l->bytestream_end)
64+ l->bytestream++;
65+ }
66+}
67+
68+/**
69+ * Decode a single byte from the compressed plane described by *l.
70+ * @param l pointer to lag_rac for the current plane
71+ * @return next byte of decoded data
72+ */
73+static inline uint8_t lag_get_rac(lag_rac *l)
74+{
75+ unsigned range_scaled, low_scaled, div;
76+ int val;
77+ uint8_t shift;
78+
79+ lag_rac_refill(l);
80+
81+ range_scaled = l->range >> l->scale;
82+
83+ if (l->low < range_scaled * l->prob[255]) {
84+ /* val = 0 is frequent enough to deserve a shortcut */
85+ if (l->low < range_scaled * l->prob[1]) {
86+ val = 0;
87+ } else {
88+ /* FIXME __builtin_clz is ~20% faster here, but not allowed in generic code. */
89+ shift = 30 - av_log2(range_scaled);
90+ div = ((range_scaled << shift) + (1 << 23) - 1) >> 23;
91+ /* low>>24 ensures that any cases too big for exact FASTDIV are
92+ * under- rather than over-estimated
93+ */
94+ low_scaled = FASTDIV(l->low - (l->low >> 24), div);
95+ shift -= l->hash_shift;
96+ shift &= 31;
97+ low_scaled = (low_scaled << shift) | (low_scaled >> (32 - shift));
98+ /* low_scaled is now a lower bound of low/range_scaled */
99+ val = l->range_hash[(uint8_t) low_scaled];
100+ while (l->low >= range_scaled * l->prob[val + 1])
101+ val++;
102+ }
103+
104+ l->range = range_scaled * (l->prob[val + 1] - l->prob[val]);
105+ } else {
106+ val = 255;
107+ l->range -= range_scaled * l->prob[255];
108+ }
109+
110+ l->low -= range_scaled * l->prob[val];
111+
112+ return val;
113+}
114+
115+
116+#endif /* AVCODEC_LAGARITHRAC_H */
libavformat/riff.c+1−0
@@ -257,6 +257,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { · 256 unmodified lines
257257 { CODEC_ID_AURA2, MKTAG('A', 'U', 'R', '2') },
258258 { CODEC_ID_DPX, MKTAG('d', 'p', 'x', ' ') },
259259 { CODEC_ID_KGV1, MKTAG('K', 'G', 'V', '1') },
260+ { CODEC_ID_LAGARITH, MKTAG('L', 'A', 'G', 'S') },
260261 { CODEC_ID_NONE, 0 }
261262 };
262263

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t