Optimize decodeplane32().
[ffmpeg.git] / libavcodec / iff.c
1 /*
2  * IFF PBM/ILBM bitmap decoder
3  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
4  * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 /**
24  * @file
25  * IFF PBM/ILBM bitmap decoder
26  */
27
28 #include "bytestream.h"
29 #include "avcodec.h"
30 #include "get_bits.h"
31 #include "iff.h"
32
33 typedef struct {
34     AVFrame frame;
35     int planesize;
36     uint8_t * planebuf;
37 } IffContext;
38
39 #define LUT8_PART(plane, v)                             \
40     AV_LE2ME64C(UINT64_C(0x0000000)<<32 | v) << plane,  \
41     AV_LE2ME64C(UINT64_C(0x1000000)<<32 | v) << plane,  \
42     AV_LE2ME64C(UINT64_C(0x0010000)<<32 | v) << plane,  \
43     AV_LE2ME64C(UINT64_C(0x1010000)<<32 | v) << plane,  \
44     AV_LE2ME64C(UINT64_C(0x0000100)<<32 | v) << plane,  \
45     AV_LE2ME64C(UINT64_C(0x1000100)<<32 | v) << plane,  \
46     AV_LE2ME64C(UINT64_C(0x0010100)<<32 | v) << plane,  \
47     AV_LE2ME64C(UINT64_C(0x1010100)<<32 | v) << plane,  \
48     AV_LE2ME64C(UINT64_C(0x0000001)<<32 | v) << plane,  \
49     AV_LE2ME64C(UINT64_C(0x1000001)<<32 | v) << plane,  \
50     AV_LE2ME64C(UINT64_C(0x0010001)<<32 | v) << plane,  \
51     AV_LE2ME64C(UINT64_C(0x1010001)<<32 | v) << plane,  \
52     AV_LE2ME64C(UINT64_C(0x0000101)<<32 | v) << plane,  \
53     AV_LE2ME64C(UINT64_C(0x1000101)<<32 | v) << plane,  \
54     AV_LE2ME64C(UINT64_C(0x0010101)<<32 | v) << plane,  \
55     AV_LE2ME64C(UINT64_C(0x1010101)<<32 | v) << plane
56
57 #define LUT8(plane) {                           \
58     LUT8_PART(plane, 0x0000000),                \
59     LUT8_PART(plane, 0x1000000),                \
60     LUT8_PART(plane, 0x0010000),                \
61     LUT8_PART(plane, 0x1010000),                \
62     LUT8_PART(plane, 0x0000100),                \
63     LUT8_PART(plane, 0x1000100),                \
64     LUT8_PART(plane, 0x0010100),                \
65     LUT8_PART(plane, 0x1010100),                \
66     LUT8_PART(plane, 0x0000001),                \
67     LUT8_PART(plane, 0x1000001),                \
68     LUT8_PART(plane, 0x0010001),                \
69     LUT8_PART(plane, 0x1010001),                \
70     LUT8_PART(plane, 0x0000101),                \
71     LUT8_PART(plane, 0x1000101),                \
72     LUT8_PART(plane, 0x0010101),                \
73     LUT8_PART(plane, 0x1010101),                \
74 }
75
76 // 8 planes * 8-bit mask
77 static const uint64_t plane8_lut[8][256] = {
78     LUT8(0), LUT8(1), LUT8(2), LUT8(3),
79     LUT8(4), LUT8(5), LUT8(6), LUT8(7),
80 };
81
82 #define LUT32(plane) {                                \
83              0,          0,          0,          0,   \
84              0,          0,          0, 1 << plane,   \
85              0,          0, 1 << plane,          0,   \
86              0,          0, 1 << plane, 1 << plane,   \
87              0, 1 << plane,          0,          0,   \
88              0, 1 << plane,          0, 1 << plane,   \
89              0, 1 << plane, 1 << plane,          0,   \
90              0, 1 << plane, 1 << plane, 1 << plane,   \
91     1 << plane,          0,          0,          0,   \
92     1 << plane,          0,          0, 1 << plane,   \
93     1 << plane,          0, 1 << plane,          0,   \
94     1 << plane,          0, 1 << plane, 1 << plane,   \
95     1 << plane, 1 << plane,          0,          0,   \
96     1 << plane, 1 << plane,          0, 1 << plane,   \
97     1 << plane, 1 << plane, 1 << plane,          0,   \
98     1 << plane, 1 << plane, 1 << plane, 1 << plane,   \
99 }
100
101 // 32 planes * 4-bit mask * 4 lookup tables each
102 static const uint32_t plane32_lut[32][16*4] = {
103     LUT32( 0), LUT32( 1), LUT32( 2), LUT32( 3),
104     LUT32( 4), LUT32( 5), LUT32( 6), LUT32( 7),
105     LUT32( 8), LUT32( 9), LUT32(10), LUT32(11),
106     LUT32(12), LUT32(13), LUT32(14), LUT32(15),
107     LUT32(16), LUT32(17), LUT32(18), LUT32(19),
108     LUT32(20), LUT32(21), LUT32(22), LUT32(23),
109     LUT32(24), LUT32(25), LUT32(26), LUT32(27),
110     LUT32(28), LUT32(29), LUT32(30), LUT32(31),
111 };
112
113 /**
114  * Convert CMAP buffer (stored in extradata) to lavc palette format
115  */
116 int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
117 {
118     int count, i;
119
120     if (avctx->bits_per_coded_sample > 8) {
121         av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
122         return AVERROR_INVALIDDATA;
123     }
124
125     count = 1 << avctx->bits_per_coded_sample;
126     if (avctx->extradata_size < count * 3) {
127         av_log(avctx, AV_LOG_ERROR, "palette data underflow\n");
128         return AVERROR_INVALIDDATA;
129     }
130     for (i=0; i < count; i++) {
131         pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 );
132     }
133     return 0;
134 }
135
136 static av_cold int decode_init(AVCodecContext *avctx)
137 {
138     IffContext *s = avctx->priv_data;
139     int err;
140
141     if (avctx->bits_per_coded_sample <= 8) {
142         avctx->pix_fmt = PIX_FMT_PAL8;
143     } else if (avctx->bits_per_coded_sample <= 32) {
144         avctx->pix_fmt = PIX_FMT_BGR32;
145     } else {
146         return AVERROR_INVALIDDATA;
147     }
148
149     if ((err = avcodec_check_dimensions(avctx, avctx->width, avctx->height)))
150         return err;
151     s->planesize = FFALIGN(avctx->width, 16) >> 3; // Align plane size in bits to word-boundary
152     s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE);
153     if (!s->planebuf)
154         return AVERROR(ENOMEM);
155
156     s->frame.reference = 1;
157     if ((err = avctx->get_buffer(avctx, &s->frame) < 0)) {
158         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
159         return err;
160     }
161
162     return avctx->bits_per_coded_sample <= 8 ?
163        ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1]) : 0;
164 }
165
166 /**
167  * Decode interleaved plane buffer up to 8bpp
168  * @param dst Destination buffer
169  * @param buf Source buffer
170  * @param buf_size
171  * @param plane plane number to decode as
172  */
173 static void decodeplane8(uint8_t *dst, const uint8_t *buf, int buf_size, int plane)
174 {
175     const uint64_t *lut = plane8_lut[plane];
176     while (buf_size--) {
177         uint64_t v = AV_RN64A(dst) | lut[*buf++];
178         AV_WN64A(dst, v);
179         dst += 8;
180     }
181 }
182
183 /**
184  * Decode interleaved plane buffer up to 24bpp
185  * @param dst Destination buffer
186  * @param buf Source buffer
187  * @param buf_size
188  * @param plane plane number to decode as
189  */
190 static void decodeplane32(uint32_t *dst, const uint8_t *buf, int buf_size, int plane)
191 {
192     const uint32_t *lut = plane32_lut[plane];
193     do {
194         unsigned mask = (*buf >> 2) & ~3;
195         dst[0] |= lut[mask++];
196         dst[1] |= lut[mask++];
197         dst[2] |= lut[mask++];
198         dst[3] |= lut[mask];
199         mask = (*buf++ << 2) & 0x3F;
200         dst[4] |= lut[mask++];
201         dst[5] |= lut[mask++];
202         dst[6] |= lut[mask++];
203         dst[7] |= lut[mask];
204         dst += 8;
205     } while (--buf_size);
206 }
207
208 static int decode_frame_ilbm(AVCodecContext *avctx,
209                             void *data, int *data_size,
210                             AVPacket *avpkt)
211 {
212     IffContext *s = avctx->priv_data;
213     const uint8_t *buf = avpkt->data;
214     int buf_size = avpkt->size;
215     const uint8_t *buf_end = buf+buf_size;
216     int y, plane;
217
218     if (avctx->reget_buffer(avctx, &s->frame) < 0){
219         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
220         return -1;
221     }
222
223     if (avctx->pix_fmt == PIX_FMT_PAL8) {
224         for(y = 0; y < avctx->height; y++ ) {
225             uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
226             memset(row, 0, avctx->width);
227             for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
228                 decodeplane8(row, buf, FFMIN(s->planesize, buf_end - buf), plane);
229                 buf += s->planesize;
230             }
231         }
232     } else { // PIX_FMT_BGR32
233         for(y = 0; y < avctx->height; y++ ) {
234             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
235             memset(row, 0, avctx->width << 2);
236             for (plane = 0; plane < avctx->bits_per_coded_sample && buf < buf_end; plane++) {
237                 decodeplane32((uint32_t *) row, buf, FFMIN(s->planesize, buf_end - buf), plane);
238                 buf += s->planesize;
239             }
240         }
241     }
242
243     *data_size = sizeof(AVFrame);
244     *(AVFrame*)data = s->frame;
245     return buf_size;
246 }
247
248 static int decode_frame_byterun1(AVCodecContext *avctx,
249                             void *data, int *data_size,
250                             AVPacket *avpkt)
251 {
252     IffContext *s = avctx->priv_data;
253     const uint8_t *buf = avpkt->data;
254     int buf_size = avpkt->size;
255     const uint8_t *buf_end = buf+buf_size;
256     int y, plane, x;
257
258     if (avctx->reget_buffer(avctx, &s->frame) < 0){
259         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
260         return -1;
261     }
262
263     if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
264         if (avctx->pix_fmt == PIX_FMT_PAL8) {
265             for(y = 0; y < avctx->height ; y++ ) {
266                 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
267                 memset(row, 0, avctx->width);
268                 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
269                     for(x = 0; x < s->planesize && buf < buf_end; ) {
270                         int8_t value = *buf++;
271                         unsigned length;
272                         if (value >= 0) {
273                             length = value + 1;
274                             memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf));
275                             buf += length;
276                         } else if (value > -128) {
277                             length = -value + 1;
278                             memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x));
279                         } else { //noop
280                             continue;
281                         }
282                         x += length;
283                     }
284                     decodeplane8(row, s->planebuf, s->planesize, plane);
285                 }
286             }
287         } else { //PIX_FMT_BGR32
288             for(y = 0; y < avctx->height ; y++ ) {
289                 uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
290                 memset(row, 0, avctx->width << 2);
291                 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
292                     for(x = 0; x < s->planesize && buf < buf_end; ) {
293                         int8_t value = *buf++;
294                         unsigned length;
295                         if (value >= 0) {
296                             length = value + 1;
297                             memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf));
298                             buf += length;
299                         } else if (value > -128) {
300                             length = -value + 1;
301                             memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x));
302                         } else { // noop
303                             continue;
304                         }
305                         x += length;
306                     }
307                     decodeplane32((uint32_t *) row, s->planebuf, s->planesize, plane);
308                 }
309             }
310         }
311     } else {
312         for(y = 0; y < avctx->height ; y++ ) {
313             uint8_t *row = &s->frame.data[0][y*s->frame.linesize[0]];
314             for(x = 0; x < avctx->width && buf < buf_end; ) {
315                 int8_t value = *buf++;
316                 unsigned length;
317                 if (value >= 0) {
318                     length = value + 1;
319                     memcpy(row + x, buf, FFMIN3(length, buf_end - buf, avctx->width - x));
320                     buf += length;
321                 } else if (value > -128) {
322                     length = -value + 1;
323                     memset(row + x, *buf++, FFMIN(length, avctx->width - x));
324                 } else { //noop
325                     continue;
326                 }
327                 x += length;
328             }
329         }
330     }
331
332     *data_size = sizeof(AVFrame);
333     *(AVFrame*)data = s->frame;
334     return buf_size;
335 }
336
337 static av_cold int decode_end(AVCodecContext *avctx)
338 {
339     IffContext *s = avctx->priv_data;
340     if (s->frame.data[0])
341         avctx->release_buffer(avctx, &s->frame);
342     av_freep(&s->planebuf);
343     return 0;
344 }
345
346 AVCodec iff_ilbm_decoder = {
347     "iff_ilbm",
348     AVMEDIA_TYPE_VIDEO,
349     CODEC_ID_IFF_ILBM,
350     sizeof(IffContext),
351     decode_init,
352     NULL,
353     decode_end,
354     decode_frame_ilbm,
355     CODEC_CAP_DR1,
356     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
357 };
358
359 AVCodec iff_byterun1_decoder = {
360     "iff_byterun1",
361     AVMEDIA_TYPE_VIDEO,
362     CODEC_ID_IFF_BYTERUN1,
363     sizeof(IffContext),
364     decode_init,
365     NULL,
366     decode_end,
367     decode_frame_byterun1,
368     CODEC_CAP_DR1,
369     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
370 };