diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2015-11-29 15:45:47 +0100 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2015-11-29 15:45:47 +0100 |
commit | 81b73f1f979557a6b94d57219e215a4479b3307b (patch) | |
tree | ee5011192efedb665f66fa70507ba7c07389dc47 | |
parent | e9675ed13ac53ec6dd7015c3a1b81043d0fea78d (diff) | |
parent | 59e3f4e598ae381600ef54e1f6e6a8a5270ac245 (diff) | |
download | ffmpeg-81b73f1f979557a6b94d57219e215a4479b3307b.tar.gz |
Merge commit '59e3f4e598ae381600ef54e1f6e6a8a5270ac245'
* commit '59e3f4e598ae381600ef54e1f6e6a8a5270ac245':
sgienc: Use a local RLE encoding function
Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
-rw-r--r-- | libavcodec/rle.c | 15 | ||||
-rw-r--r-- | libavcodec/rle.h | 11 | ||||
-rw-r--r-- | libavcodec/sgienc.c | 45 |
3 files changed, 54 insertions, 17 deletions
diff --git a/libavcodec/rle.c b/libavcodec/rle.c index d2ec68c407..7924ea780f 100644 --- a/libavcodec/rle.c +++ b/libavcodec/rle.c @@ -22,16 +22,7 @@ #include "rle.h" #include "libavutil/common.h" -/** - * Count up to 127 consecutive pixels which are either all the same or - * all differ from the previous and next pixels. - * @param start Pointer to the first pixel - * @param len Maximum number of pixels - * @param bpp Bytes per pixel - * @param same 1 if searching for identical pixel values. 0 for differing - * @return Number of matching consecutive pixels found - */ -static int count_pixels(const uint8_t *start, int len, int bpp, int same) +int ff_rle_count_pixels(const uint8_t *start, int len, int bpp, int same) { const uint8_t *pos; int count = 1; @@ -63,14 +54,14 @@ int ff_rle_encode(uint8_t *outbuf, int out_size, const uint8_t *ptr , int bpp, i for(x = 0; x < w; x += count) { /* see if we can encode the next set of pixels with RLE */ - if((count = count_pixels(ptr, w-x, bpp, 1)) > 1) { + if ((count = ff_rle_count_pixels(ptr, w - x, bpp, 1)) > 1) { if(out + bpp + 1 > outbuf + out_size) return -1; *out++ = (count ^ xor_rep) + add_rep; memcpy(out, ptr, bpp); out += bpp; } else { /* fall back on uncompressed */ - count = count_pixels(ptr, w-x, bpp, 0); + count = ff_rle_count_pixels(ptr, w - x, bpp, 0); if(out + bpp*count >= outbuf + out_size) return -1; *out++ = (count ^ xor_raw) + add_raw; diff --git a/libavcodec/rle.h b/libavcodec/rle.h index 24851321fe..cb51624975 100644 --- a/libavcodec/rle.h +++ b/libavcodec/rle.h @@ -24,6 +24,17 @@ #include <stdint.h> /** + * Count up to 127 consecutive pixels which are either all the same or + * all differ from the previous and next pixels. + * @param start Pointer to the first pixel + * @param len Maximum number of pixels + * @param bpp Bytes per pixel + * @param same 1 if searching for identical pixel values, 0 for differing + * @return Number of matching consecutive pixels found + */ +int ff_rle_count_pixels(const uint8_t *start, int len, int bpp, int same); + +/** * RLE compress the row, with maximum size of out_size. Value before repeated bytes is (count ^ xor_rep) + add_rep. * Value before raw bytes is (count ^ xor_raw) + add_raw. * @param outbuf Output buffer diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index 4477fe1d1a..4d5de9d29b 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -40,6 +40,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) { @@ -111,7 +149,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_packet2(avctx, pkt, bytes_per_channel * length, 0)) < 0) @@ -165,15 +203,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]; } |