From 4231bbbf4c54c22fbda6832002675b43f24d3802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Sun, 8 Jan 2012 12:19:48 +0100 Subject: [PATCH] sgidec: make compiler optimize away memcpy call in inner loop. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using an always_inline function makes the memcpy length a constant, any reasonable compiler will replace it by a single mov instruction without us having to duplicate the actual code. Signed-off-by: Reimar Döffinger --- libavcodec/sgidec.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index ae05d83592..98327a86a9 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -20,6 +20,7 @@ */ #include "libavutil/imgutils.h" +#include "libavutil/avassert.h" #include "avcodec.h" #include "bytestream.h" #include "sgi.h" @@ -113,6 +114,25 @@ static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, return 0; } +static av_always_inline void copy_loop(uint8_t *out_buf, const uint8_t *in_buf, + unsigned offset, unsigned bytes_per_channel, + SgiState *s) +{ + int x, y, z; + for (y = s->height - 1; y >= 0; y--) { + uint8_t *line = out_buf + (y * s->linesize); + for (x = s->width; x > 0; x--) { + const uint8_t *ptr = in_buf; + in_buf += bytes_per_channel; + for(z = 0; z < s->depth; z ++) { + memcpy(line, ptr, bytes_per_channel); + line += bytes_per_channel; + ptr += offset; + } + } + } +} + /** * Read an uncompressed SGI image. * @param out_buf output buffer @@ -125,8 +145,6 @@ static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, const uint8_t *in_buf, const uint8_t *in_end, SgiState* s) { - int x, y, z; - const uint8_t *ptr; unsigned int offset = s->height * s->width * s->bytes_per_channel; /* Test buffer size. */ @@ -134,17 +152,11 @@ static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, return -1; } - for (y = s->height - 1; y >= 0; y--) { - out_end = out_buf + (y * s->linesize); - for (x = s->width; x > 0; x--) { - ptr = in_buf; - in_buf += s->bytes_per_channel; - for(z = 0; z < s->depth; z ++) { - memcpy(out_end, ptr, s->bytes_per_channel); - out_end += s->bytes_per_channel; - ptr += offset; - } - } + if (s->bytes_per_channel == 2) { + copy_loop(out_buf, in_buf, offset, 2, s); + } else { + av_assert1(s->bytes_per_channel == 1); + copy_loop(out_buf, in_buf, offset, 1, s); } return 0; }