[FFmpeg-cvslog] sgidec: make compiler optimize away memcpy call in inner loop.

Reimar Döffinger git at videolan.org
Mon Jan 9 11:03:59 CET 2012


ffmpeg | branch: master | Reimar Döffinger <Reimar.Doeffinger at gmx.de> | Sun Jan  8 12:19:48 2012 +0100| [4231bbbf4c54c22fbda6832002675b43f24d3802] | committer: Reimar Döffinger

sgidec: make compiler optimize away memcpy call in inner loop.

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 <Reimar.Doeffinger at gmx.de>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=4231bbbf4c54c22fbda6832002675b43f24d3802
---

 libavcodec/sgidec.c |   38 +++++++++++++++++++++++++-------------
 1 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c
index ae05d83..98327a8 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;
 }



More information about the ffmpeg-cvslog mailing list