From 59e3f4e598ae381600ef54e1f6e6a8a5270ac245 Mon Sep 17 00:00:00 2001 From: Vittorio Giovara Date: Fri, 20 Nov 2015 02:17:33 +0100 Subject: sgienc: Use a local RLE encoding function SGI RLE encoding is slighlty different than the one provided by rle module (especially at high bit depth). The pixel count function however does not change, so it is simply made library-public. --- libavcodec/sgienc.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'libavcodec/sgienc.c') diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index a449f8c03b..236c72b250 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -39,6 +39,44 @@ static av_cold int encode_init(AVCodecContext *avctx) return 0; } +static int sgi_rle_encode(PutByteContext *pbc, const uint8_t *src, + int w, int bpp) +{ + int val, count, x, start = bytestream2_tell_p(pbc); + void (*bytestream2_put)(PutByteContext *, unsigned int); + + bytestream2_put = bytestream2_put_byte; + + for (x = 0; x < w; x += count) { + /* see if we can encode the next set of pixels with RLE */ + count = ff_rle_count_pixels(src, w - x, bpp, 1); + if (count > 1) { + if (bytestream2_get_bytes_left_p(pbc) < bpp * 2) + return AVERROR_INVALIDDATA; + + val = *src; + bytestream2_put(pbc, count); + bytestream2_put(pbc, val); + } else { + int i; + /* fall back on uncompressed */ + count = ff_rle_count_pixels(src, w - x, bpp, 0); + if (bytestream2_get_bytes_left_p(pbc) < bpp * (count + 1)) + return AVERROR_INVALIDDATA; + + bytestream2_put(pbc, count + 0x80); + for (i = 0; i < count; i++) { + val = src[i]; + bytestream2_put(pbc, val); + } + } + + src += count * bpp; + } + + return bytestream2_tell_p(pbc) - start; +} + static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -110,7 +148,7 @@ FF_ENABLE_DEPRECATION_WARNINGS length = SGI_HEADER_SIZE; if (avctx->coder_type == FF_CODER_TYPE_RAW) length += depth * height * width; - else // assume ff_rl_encode() produces at most 2x size of input + else // assume sgi_rle_encode() produces at most 2x size of input length += tablesize * 2 + depth * height * (2 * width + 1); if ((ret = ff_alloc_packet(pkt, bytes_per_channel * length)) < 0) { @@ -166,15 +204,12 @@ FF_ENABLE_DEPRECATION_WARNINGS for (x = 0; x < width; x++) encode_buf[x] = in_buf[depth * x]; - length = ff_rle_encode(pbc.buffer, - bytestream2_get_bytes_left_p(&pbc), - encode_buf, 1, width, 0, 0, 0x80, 0); + length = sgi_rle_encode(&pbc, encode_buf, width, 1); if (length < 1) { av_free(encode_buf); return -1; } - bytestream2_skip_p(&pbc, length); bytestream2_put_be32(&tablen_pcb, length); in_buf -= p->linesize[0]; } -- cgit v1.2.3