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@gmx.de>
... | ... |
@@ -20,6 +20,7 @@ |
20 | 20 |
*/ |
21 | 21 |
|
22 | 22 |
#include "libavutil/imgutils.h" |
23 |
+#include "libavutil/avassert.h" |
|
23 | 24 |
#include "avcodec.h" |
24 | 25 |
#include "bytestream.h" |
25 | 26 |
#include "sgi.h" |
... | ... |
@@ -113,6 +114,25 @@ static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, |
113 | 113 |
return 0; |
114 | 114 |
} |
115 | 115 |
|
116 |
+static av_always_inline void copy_loop(uint8_t *out_buf, const uint8_t *in_buf, |
|
117 |
+ unsigned offset, unsigned bytes_per_channel, |
|
118 |
+ SgiState *s) |
|
119 |
+{ |
|
120 |
+ int x, y, z; |
|
121 |
+ for (y = s->height - 1; y >= 0; y--) { |
|
122 |
+ uint8_t *line = out_buf + (y * s->linesize); |
|
123 |
+ for (x = s->width; x > 0; x--) { |
|
124 |
+ const uint8_t *ptr = in_buf; |
|
125 |
+ in_buf += bytes_per_channel; |
|
126 |
+ for(z = 0; z < s->depth; z ++) { |
|
127 |
+ memcpy(line, ptr, bytes_per_channel); |
|
128 |
+ line += bytes_per_channel; |
|
129 |
+ ptr += offset; |
|
130 |
+ } |
|
131 |
+ } |
|
132 |
+ } |
|
133 |
+} |
|
134 |
+ |
|
116 | 135 |
/** |
117 | 136 |
* Read an uncompressed SGI image. |
118 | 137 |
* @param out_buf output buffer |
... | ... |
@@ -125,8 +145,6 @@ static int read_rle_sgi(unsigned char* out_buf, const uint8_t *in_buf, |
125 | 125 |
static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, |
126 | 126 |
const uint8_t *in_buf, const uint8_t *in_end, SgiState* s) |
127 | 127 |
{ |
128 |
- int x, y, z; |
|
129 |
- const uint8_t *ptr; |
|
130 | 128 |
unsigned int offset = s->height * s->width * s->bytes_per_channel; |
131 | 129 |
|
132 | 130 |
/* Test buffer size. */ |
... | ... |
@@ -134,17 +152,11 @@ static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end, |
134 | 134 |
return -1; |
135 | 135 |
} |
136 | 136 |
|
137 |
- for (y = s->height - 1; y >= 0; y--) { |
|
138 |
- out_end = out_buf + (y * s->linesize); |
|
139 |
- for (x = s->width; x > 0; x--) { |
|
140 |
- ptr = in_buf; |
|
141 |
- in_buf += s->bytes_per_channel; |
|
142 |
- for(z = 0; z < s->depth; z ++) { |
|
143 |
- memcpy(out_end, ptr, s->bytes_per_channel); |
|
144 |
- out_end += s->bytes_per_channel; |
|
145 |
- ptr += offset; |
|
146 |
- } |
|
147 |
- } |
|
137 |
+ if (s->bytes_per_channel == 2) { |
|
138 |
+ copy_loop(out_buf, in_buf, offset, 2, s); |
|
139 |
+ } else { |
|
140 |
+ av_assert1(s->bytes_per_channel == 1); |
|
141 |
+ copy_loop(out_buf, in_buf, offset, 1, s); |
|
148 | 142 |
} |
149 | 143 |
return 0; |
150 | 144 |
} |