Use int8_t instead of char, the signedness of char can differ between systems.
[ffmpeg.git] / libavcodec / iff.c
1 /*
2  * IFF PBM/ILBM bitmap decoder
3  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21
22 /**
23  * @file libavcodec/iff.c
24  * IFF PBM/ILBM bitmap decoder
25  */
26
27 #include "bytestream.h"
28 #include "avcodec.h"
29
30 /**
31  * Convert CMAP buffer (stored in extradata) to lavc palette format
32  */
33 int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal)
34 {
35     int count, i;
36
37     if (avctx->bits_per_coded_sample > 8) {
38         av_log(avctx, AV_LOG_ERROR, "bit_per_coded_sample > 8 not supported\n");
39         return AVERROR_INVALIDDATA;
40     }
41
42     count = 1 << avctx->bits_per_coded_sample;
43     if (avctx->extradata_size < count * 3) {
44         av_log(avctx, AV_LOG_ERROR, "palette data underflow\n");
45         return AVERROR_INVALIDDATA;
46     }
47     for (i=0; i < count; i++) {
48         pal[i] = AV_RB24( avctx->extradata + i*3 );
49     }
50     return 0;
51 }
52
53 static av_cold int decode_init(AVCodecContext *avctx)
54 {
55     AVFrame *frame = avctx->priv_data;
56
57     avctx->pix_fmt = PIX_FMT_PAL8;
58     frame->reference = 1;
59
60     if (avctx->get_buffer(avctx, frame) < 0) {
61         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
62         return AVERROR_UNKNOWN;
63     }
64     return ff_cmap_read_palette(avctx, (uint32_t*)frame->data[1]);
65 }
66
67 /**
68  * Interleaved memcpy
69  */
70 static void imemcpy(uint8_t *dst, const uint8_t const *buf, int x, int bps, int plane, int length)
71 {
72     int i, b;
73     for(i = 0; i < length; i++) {
74         int value = buf[i];
75         for (b = 0; b < bps; b++) {
76             if (value & (1<<b))
77                 dst[ (x+i)*bps + 7 - b] |= 1<<plane;
78        }
79     }
80 }
81
82 /**
83  * Interleaved memset
84  */
85 static void imemset(uint8_t *dst, int value, int x, int bps, int plane, int length)
86 {
87     int i, b;
88     for(i = 0; i < length; i++) {
89         for (b = 0; b < bps; b++) {
90             if (value & (1<<b))
91                 dst[ (x+i)*bps + 7 - b] |= 1<<plane;
92        }
93     }
94 }
95
96 static int decode_frame_ilbm(AVCodecContext *avctx,
97                             void *data, int *data_size,
98                             AVPacket *avpkt)
99 {
100     AVFrame *frame = avctx->priv_data;
101     const uint8_t *buf = avpkt->data;
102     int buf_size = avpkt->size;
103     int planewidth = avctx->width / avctx->bits_per_coded_sample;
104     int y, plane;
105
106     if (avctx->reget_buffer(avctx, frame) < 0){
107         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
108         return -1;
109     }
110
111     if (buf_size < avctx->width * avctx->height) {
112         av_log(avctx, AV_LOG_ERROR, "buffer underflow\n");
113         return -1;
114     }
115
116     for(y = 0; y < avctx->height; y++ ) {
117         uint8_t *row = &frame->data[0][ y*frame->linesize[0] ];
118         memset(row, 0, avctx->width);
119         for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
120             imemcpy(row, buf, 0, avctx->bits_per_coded_sample, plane, planewidth);
121             buf += planewidth;
122         }
123     }
124
125     *data_size = sizeof(AVFrame);
126     *(AVFrame*)data = *frame;
127     return buf_size;
128 }
129
130 static int decode_frame_byterun1(AVCodecContext *avctx,
131                             void *data, int *data_size,
132                             AVPacket *avpkt)
133 {
134     AVFrame *frame = avctx->priv_data;
135     const uint8_t *buf = avpkt->data;
136     int buf_size = avpkt->size;
137     const uint8_t *buf_end = buf+buf_size;
138     int planewidth = avctx->width / avctx->bits_per_coded_sample;
139     int y, plane, x;
140
141     if (avctx->reget_buffer(avctx, frame) < 0){
142         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
143         return -1;
144     }
145
146     for(y = 0; y < avctx->height ; y++ ) {
147         uint8_t *row = &frame->data[0][ y*frame->linesize[0] ];
148         if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved
149             memset(row, 0, avctx->width);
150             for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) {
151                 for(x = 0; x < planewidth && buf < buf_end; ) {
152                     int8_t value = *buf++;
153                     int length;
154                     if (value >= 0) {
155                         length = value + 1;
156                         imemcpy(row, buf, x, avctx->bits_per_coded_sample, plane, FFMIN3(length, buf_end - buf, planewidth - x));
157                         buf += length;
158                     } else if (value > -128) {
159                         length = -value + 1;
160                         imemset(row, *buf++, x, avctx->bits_per_coded_sample, plane, FFMIN(length, planewidth - x));
161                     } else { //noop
162                         continue;
163                     }
164                     x += length;
165                 }
166             }
167         } else {
168             for(x = 0; x < avctx->width && buf < buf_end; ) {
169                 int8_t value = *buf++;
170                 int length;
171                 if (value >= 0) {
172                     length = value + 1;
173                     memcpy(row + x, buf, FFMIN3(length, buf_end - buf, avctx->width - x));
174                     buf += length;
175                 } else if (value > -128) {
176                     length = -value + 1;
177                     memset(row + x, *buf++, FFMIN(length, avctx->width - x));
178                 } else { //noop
179                     continue;
180                 }
181                 x += length;
182             }
183         }
184     }
185
186     *data_size = sizeof(AVFrame);
187     *(AVFrame*)data = *frame;
188     return buf_size;
189 }
190
191 static av_cold int decode_end(AVCodecContext *avctx)
192 {
193     AVFrame *frame = avctx->priv_data;
194     if (frame->data[0])
195         avctx->release_buffer(avctx, frame);
196     return 0;
197 }
198
199 AVCodec iff_ilbm_decoder = {
200     "iff_ilbm",
201     CODEC_TYPE_VIDEO,
202     CODEC_ID_IFF_ILBM,
203     sizeof(AVFrame),
204     decode_init,
205     NULL,
206     decode_end,
207     decode_frame_ilbm,
208     CODEC_CAP_DR1,
209     .long_name = NULL_IF_CONFIG_SMALL("IFF ILBM"),
210 };
211
212 AVCodec iff_byterun1_decoder = {
213     "iff_byterun1",
214     CODEC_TYPE_VIDEO,
215     CODEC_ID_IFF_BYTERUN1,
216     sizeof(AVFrame),
217     decode_init,
218     NULL,
219     decode_end,
220     decode_frame_byterun1,
221     CODEC_CAP_DR1,
222     .long_name = NULL_IF_CONFIG_SMALL("IFF ByteRun1"),
223 };