diff options
author | James Almer <jamrial@gmail.com> | 2014-08-23 06:39:57 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-08-24 03:21:39 +0400 |
commit | b140b51ebbc277fa558accc33f3e99da2b9657b3 (patch) | |
tree | ea1db181210e86040569f0e62ef576c3e1b8c304 /libavcodec | |
parent | 2e3c1699aea7bb5a72d18903f4b8d3d33964c14d (diff) |
lavc/tiff: add support for LZMA compression
Derived from deflate code.
Requires liblzma.
Signed-off-by: James Almer <jamrial@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/tiff.c | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 2bb7c906c4..613ad3d9e0 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -28,6 +28,9 @@ #if CONFIG_ZLIB #include <zlib.h> #endif +#if CONFIG_LZMA +#include <lzma.h> +#endif #include "libavutil/attributes.h" #include "libavutil/avstring.h" @@ -378,6 +381,70 @@ static int tiff_unpack_zlib(TiffContext *s, AVFrame *p, uint8_t *dst, int stride } #endif +#if CONFIG_LZMA +static int tiff_uncompress_lzma(uint8_t *dst, uint64_t *len, const uint8_t *src, + int size) +{ + lzma_stream stream = LZMA_STREAM_INIT; + lzma_ret ret; + + stream.next_in = (uint8_t *)src; + stream.avail_in = size; + stream.next_out = dst; + stream.avail_out = *len; + ret = lzma_stream_decoder(&stream, UINT64_MAX, 0); + if (ret != LZMA_OK) { + av_log(NULL, AV_LOG_ERROR, "LZMA init error: %d\n", ret); + return ret; + } + ret = lzma_code(&stream, LZMA_RUN); + lzma_end(&stream); + *len = stream.total_out; + return ret == LZMA_STREAM_END ? LZMA_OK : ret; +} + +static int tiff_unpack_lzma(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, + const uint8_t *src, int size, int width, int lines, + int strip_start, int is_yuv) +{ + uint64_t outlen = width * lines; + int ret, line; + uint8_t *buf = av_malloc(outlen); + if (!buf) + return AVERROR(ENOMEM); + if (s->fill_order) { + if ((ret = deinvert_buffer(s, src, size)) < 0) { + av_free(buf); + return ret; + } + src = s->deinvert_buf; + } + ret = tiff_uncompress_lzma(buf, &outlen, src, size); + if (ret != LZMA_OK) { + av_log(s->avctx, AV_LOG_ERROR, + "Uncompressing failed (%"PRIu64" of %"PRIu64") with error %d\n", outlen, + (uint64_t)width * lines, ret); + av_free(buf); + return AVERROR_UNKNOWN; + } + src = buf; + for (line = 0; line < lines; line++) { + if (s->bpp < 8 && s->avctx->pix_fmt == AV_PIX_FMT_PAL8) { + horizontal_fill(s->bpp, dst, 1, src, 0, width, 0); + } else { + memcpy(dst, src, width); + } + if (is_yuv) { + unpack_yuv(s, p, dst, strip_start + line); + line += s->subsampling[1] - 1; + } + dst += stride; + src += width; + } + av_free(buf); + return 0; +} +#endif static int tiff_unpack_fax(TiffContext *s, uint8_t *dst, int stride, const uint8_t *src, int size, int width, int lines) @@ -457,6 +524,16 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid return AVERROR(ENOSYS); #endif } + if (s->compr == TIFF_LZMA) { +#if CONFIG_LZMA + return tiff_unpack_lzma(s, p, dst, stride, src, size, width, lines, + strip_start, is_yuv); +#else + av_log(s->avctx, AV_LOG_ERROR, + "LZMA support not enabled\n"); + return AVERROR(ENOSYS); +#endif + } if (s->compr == TIFF_LZW) { if (s->fill_order) { if ((ret = deinvert_buffer(s, src, size)) < 0) @@ -783,8 +860,12 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) avpriv_report_missing_feature(s->avctx, "JPEG compression"); return AVERROR_PATCHWELCOME; case TIFF_LZMA: - avpriv_report_missing_feature(s->avctx, "LZMA compression"); - return AVERROR_PATCHWELCOME; +#if CONFIG_LZMA + break; +#else + av_log(s->avctx, AV_LOG_ERROR, "LZMA not compiled in\n"); + return AVERROR(ENOSYS); +#endif default: av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", s->compr); |