From b140b51ebbc277fa558accc33f3e99da2b9657b3 Mon Sep 17 00:00:00 2001 From: James Almer Date: Fri, 22 Aug 2014 23:39:57 -0300 Subject: lavc/tiff: add support for LZMA compression Derived from deflate code. Requires liblzma. Signed-off-by: James Almer Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 2 deletions(-) (limited to 'libavcodec/tiff.c') 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 #endif +#if CONFIG_LZMA +#include +#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) @@ -455,6 +522,16 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid "zlib support not enabled, " "deflate compression not supported\n"); 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) { @@ -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); -- cgit v1.2.3