summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/rle.c15
-rw-r--r--libavcodec/rle.h11
-rw-r--r--libavcodec/sgienc.c45
3 files changed, 54 insertions, 17 deletions
diff --git a/libavcodec/rle.c b/libavcodec/rle.c
index cbbde93f56..8a2d922ab6 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 00261d3598..c9677647cb 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 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];
}