Mercurial > libavcodec.hg
comparison iff.c @ 11175:30856cadb01b libavcodec
IFF bitmap n-bit color support
author | pross |
---|---|
date | Mon, 15 Feb 2010 11:26:35 +0000 |
parents | 85a1b00a2413 |
children | a4c6587e2c27 |
comparison
equal
deleted
inserted
replaced
11174:421c6cd2fb9f | 11175:30856cadb01b |
---|---|
24 * IFF PBM/ILBM bitmap decoder | 24 * IFF PBM/ILBM bitmap decoder |
25 */ | 25 */ |
26 | 26 |
27 #include "bytestream.h" | 27 #include "bytestream.h" |
28 #include "avcodec.h" | 28 #include "avcodec.h" |
29 #include "get_bits.h" | |
30 | |
31 typedef struct { | |
32 AVFrame frame; | |
33 int planesize; | |
34 uint8_t * planebuf; | |
35 } IffContext; | |
29 | 36 |
30 /** | 37 /** |
31 * Convert CMAP buffer (stored in extradata) to lavc palette format | 38 * Convert CMAP buffer (stored in extradata) to lavc palette format |
32 */ | 39 */ |
33 int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) | 40 int ff_cmap_read_palette(AVCodecContext *avctx, uint32_t *pal) |
43 if (avctx->extradata_size < count * 3) { | 50 if (avctx->extradata_size < count * 3) { |
44 av_log(avctx, AV_LOG_ERROR, "palette data underflow\n"); | 51 av_log(avctx, AV_LOG_ERROR, "palette data underflow\n"); |
45 return AVERROR_INVALIDDATA; | 52 return AVERROR_INVALIDDATA; |
46 } | 53 } |
47 for (i=0; i < count; i++) { | 54 for (i=0; i < count; i++) { |
48 pal[i] = AV_RB24( avctx->extradata + i*3 ); | 55 pal[i] = 0xFF000000 | AV_RB24( avctx->extradata + i*3 ); |
49 } | 56 } |
50 return 0; | 57 return 0; |
51 } | 58 } |
52 | 59 |
53 static av_cold int decode_init(AVCodecContext *avctx) | 60 static av_cold int decode_init(AVCodecContext *avctx) |
54 { | 61 { |
55 AVFrame *frame = avctx->priv_data; | 62 IffContext *s = avctx->priv_data; |
56 | 63 |
57 avctx->pix_fmt = PIX_FMT_PAL8; | 64 if (avctx->bits_per_coded_sample <= 8) { |
58 frame->reference = 1; | 65 avctx->pix_fmt = PIX_FMT_PAL8; |
59 | 66 } else if (avctx->bits_per_coded_sample <= 32) { |
60 if (avctx->get_buffer(avctx, frame) < 0) { | 67 avctx->pix_fmt = PIX_FMT_BGR32; |
68 } else { | |
69 return AVERROR_INVALIDDATA; | |
70 } | |
71 | |
72 s->planesize = avctx->width / 8; | |
73 s->planebuf = av_malloc(s->planesize + FF_INPUT_BUFFER_PADDING_SIZE); | |
74 if (!s->planebuf) | |
75 return AVERROR(ENOMEM); | |
76 | |
77 s->frame.reference = 1; | |
78 if (avctx->get_buffer(avctx, &s->frame) < 0) { | |
61 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | 79 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
62 return AVERROR_UNKNOWN; | 80 return AVERROR_UNKNOWN; |
63 } | 81 } |
64 return ff_cmap_read_palette(avctx, (uint32_t*)frame->data[1]); | 82 |
83 return avctx->bits_per_coded_sample <= 8 ? | |
84 ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1]) : 0; | |
65 } | 85 } |
66 | 86 |
67 /** | 87 /** |
68 * Interleaved memcpy | 88 * Decode interleaved plane buffer |
69 */ | 89 * @param dst Destination buffer |
70 static void imemcpy(uint8_t *dst, const uint8_t const *buf, int x, int bps, int plane, int length) | 90 * @param buf Source buffer |
71 { | 91 * @param buf_size |
72 int i, b; | 92 * @param bps bits_per_coded_sample |
73 for(i = 0; i < length; i++) { | 93 * @param plane plane number to decode as |
74 int value = buf[i]; | 94 */ |
75 for (b = 0; b < bps; b++) { | 95 #define DECLARE_DECODEPLANE(suffix, type) \ |
76 if (value & (1<<b)) | 96 static void decodeplane##suffix(void *dst, const uint8_t const *buf, int buf_size, int bps, int plane) \ |
77 dst[ (x+i)*bps + 7 - b] |= 1<<plane; | 97 { \ |
78 } | 98 GetBitContext gb; \ |
79 } | 99 int i, b; \ |
80 } | 100 init_get_bits(&gb, buf, buf_size * 8); \ |
81 | 101 for(i = 0; i < (buf_size * 8 + bps - 1) / bps; i++) { \ |
82 /** | 102 for (b = 0; b < bps; b++) { \ |
83 * Interleaved memset | 103 ((type *)dst)[ i*bps + b ] |= get_bits1(&gb) << plane; \ |
84 */ | 104 } \ |
85 static void imemset(uint8_t *dst, int value, int x, int bps, int plane, int length) | 105 } \ |
86 { | 106 } |
87 int i, b; | 107 DECLARE_DECODEPLANE(8, uint8_t) |
88 for(i = 0; i < length; i++) { | 108 DECLARE_DECODEPLANE(32, uint32_t) |
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 | 109 |
96 static int decode_frame_ilbm(AVCodecContext *avctx, | 110 static int decode_frame_ilbm(AVCodecContext *avctx, |
97 void *data, int *data_size, | 111 void *data, int *data_size, |
98 AVPacket *avpkt) | 112 AVPacket *avpkt) |
99 { | 113 { |
100 AVFrame *frame = avctx->priv_data; | 114 IffContext *s = avctx->priv_data; |
101 const uint8_t *buf = avpkt->data; | 115 const uint8_t *buf = avpkt->data; |
102 int buf_size = avpkt->size; | 116 int buf_size = avpkt->size; |
103 int planewidth = avctx->width / avctx->bits_per_coded_sample; | |
104 int y, plane; | 117 int y, plane; |
105 | 118 |
106 if (avctx->reget_buffer(avctx, frame) < 0){ | 119 if (avctx->reget_buffer(avctx, &s->frame) < 0){ |
107 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | 120 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
108 return -1; | 121 return -1; |
109 } | 122 } |
110 | 123 |
111 if (buf_size < avctx->width * avctx->height) { | 124 if (buf_size < avctx->width * avctx->height) { |
112 av_log(avctx, AV_LOG_ERROR, "buffer underflow\n"); | 125 av_log(avctx, AV_LOG_ERROR, "buffer underflow\n"); |
113 return -1; | 126 return -1; |
114 } | 127 } |
115 | 128 |
116 for(y = 0; y < avctx->height; y++ ) { | 129 for(y = 0; y < avctx->height; y++ ) { |
117 uint8_t *row = &frame->data[0][ y*frame->linesize[0] ]; | 130 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ]; |
118 memset(row, 0, avctx->width); | 131 memset(row, 0, avctx->pix_fmt == PIX_FMT_PAL8 ? avctx->width : (avctx->width * 4)); |
119 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { | 132 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { |
120 imemcpy(row, buf, 0, avctx->bits_per_coded_sample, plane, planewidth); | 133 if (avctx->pix_fmt == PIX_FMT_PAL8) { |
121 buf += planewidth; | 134 decodeplane8(row, buf, s->planesize, avctx->bits_per_coded_sample, plane); |
135 } else { // PIX_FMT_BGR32 | |
136 decodeplane32(row, buf, s->planesize, avctx->bits_per_coded_sample, plane); | |
137 } | |
138 buf += s->planesize; | |
122 } | 139 } |
123 } | 140 } |
124 | 141 |
125 *data_size = sizeof(AVFrame); | 142 *data_size = sizeof(AVFrame); |
126 *(AVFrame*)data = *frame; | 143 *(AVFrame*)data = s->frame; |
127 return buf_size; | 144 return buf_size; |
128 } | 145 } |
129 | 146 |
130 static int decode_frame_byterun1(AVCodecContext *avctx, | 147 static int decode_frame_byterun1(AVCodecContext *avctx, |
131 void *data, int *data_size, | 148 void *data, int *data_size, |
132 AVPacket *avpkt) | 149 AVPacket *avpkt) |
133 { | 150 { |
134 AVFrame *frame = avctx->priv_data; | 151 IffContext *s = avctx->priv_data; |
135 const uint8_t *buf = avpkt->data; | 152 const uint8_t *buf = avpkt->data; |
136 int buf_size = avpkt->size; | 153 int buf_size = avpkt->size; |
137 const uint8_t *buf_end = buf+buf_size; | 154 const uint8_t *buf_end = buf+buf_size; |
138 int planewidth = avctx->width / avctx->bits_per_coded_sample; | |
139 int y, plane, x; | 155 int y, plane, x; |
140 | 156 |
141 if (avctx->reget_buffer(avctx, frame) < 0){ | 157 if (avctx->reget_buffer(avctx, &s->frame) < 0){ |
142 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | 158 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
143 return -1; | 159 return -1; |
144 } | 160 } |
145 | 161 |
146 for(y = 0; y < avctx->height ; y++ ) { | 162 for(y = 0; y < avctx->height ; y++ ) { |
147 uint8_t *row = &frame->data[0][ y*frame->linesize[0] ]; | 163 uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ]; |
148 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved | 164 if (avctx->codec_tag == MKTAG('I','L','B','M')) { //interleaved |
149 memset(row, 0, avctx->width); | 165 memset(row, 0, avctx->pix_fmt == PIX_FMT_PAL8 ? avctx->width : (avctx->width * 4)); |
150 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { | 166 for (plane = 0; plane < avctx->bits_per_coded_sample; plane++) { |
151 for(x = 0; x < planewidth && buf < buf_end; ) { | 167 for(x = 0; x < s->planesize && buf < buf_end; ) { |
152 int8_t value = *buf++; | 168 int8_t value = *buf++; |
153 int length; | 169 int length; |
154 if (value >= 0) { | 170 if (value >= 0) { |
155 length = value + 1; | 171 length = value + 1; |
156 imemcpy(row, buf, x, avctx->bits_per_coded_sample, plane, FFMIN3(length, buf_end - buf, planewidth - x)); | 172 memcpy(s->planebuf + x, buf, FFMIN3(length, s->planesize - x, buf_end - buf)); |
157 buf += length; | 173 buf += length; |
158 } else if (value > -128) { | 174 } else if (value > -128) { |
159 length = -value + 1; | 175 length = -value + 1; |
160 imemset(row, *buf++, x, avctx->bits_per_coded_sample, plane, FFMIN(length, planewidth - x)); | 176 memset(s->planebuf + x, *buf++, FFMIN(length, s->planesize - x)); |
161 } else { //noop | 177 } else { //noop |
162 continue; | 178 continue; |
163 } | 179 } |
164 x += length; | 180 x += length; |
181 } | |
182 if (avctx->pix_fmt == PIX_FMT_PAL8) { | |
183 decodeplane8(row, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane); | |
184 } else { //PIX_FMT_BGR32 | |
185 decodeplane32(row, s->planebuf, s->planesize, avctx->bits_per_coded_sample, plane); | |
165 } | 186 } |
166 } | 187 } |
167 } else { | 188 } else { |
168 for(x = 0; x < avctx->width && buf < buf_end; ) { | 189 for(x = 0; x < avctx->width && buf < buf_end; ) { |
169 int8_t value = *buf++; | 190 int8_t value = *buf++; |
182 } | 203 } |
183 } | 204 } |
184 } | 205 } |
185 | 206 |
186 *data_size = sizeof(AVFrame); | 207 *data_size = sizeof(AVFrame); |
187 *(AVFrame*)data = *frame; | 208 *(AVFrame*)data = s->frame; |
188 return buf_size; | 209 return buf_size; |
189 } | 210 } |
190 | 211 |
191 static av_cold int decode_end(AVCodecContext *avctx) | 212 static av_cold int decode_end(AVCodecContext *avctx) |
192 { | 213 { |
193 AVFrame *frame = avctx->priv_data; | 214 IffContext *s = avctx->priv_data; |
194 if (frame->data[0]) | 215 if (s->frame.data[0]) |
195 avctx->release_buffer(avctx, frame); | 216 avctx->release_buffer(avctx, &s->frame); |
217 av_freep(&s->planebuf); | |
196 return 0; | 218 return 0; |
197 } | 219 } |
198 | 220 |
199 AVCodec iff_ilbm_decoder = { | 221 AVCodec iff_ilbm_decoder = { |
200 "iff_ilbm", | 222 "iff_ilbm", |
201 CODEC_TYPE_VIDEO, | 223 CODEC_TYPE_VIDEO, |
202 CODEC_ID_IFF_ILBM, | 224 CODEC_ID_IFF_ILBM, |
203 sizeof(AVFrame), | 225 sizeof(IffContext), |
204 decode_init, | 226 decode_init, |
205 NULL, | 227 NULL, |
206 decode_end, | 228 decode_end, |
207 decode_frame_ilbm, | 229 decode_frame_ilbm, |
208 CODEC_CAP_DR1, | 230 CODEC_CAP_DR1, |
211 | 233 |
212 AVCodec iff_byterun1_decoder = { | 234 AVCodec iff_byterun1_decoder = { |
213 "iff_byterun1", | 235 "iff_byterun1", |
214 CODEC_TYPE_VIDEO, | 236 CODEC_TYPE_VIDEO, |
215 CODEC_ID_IFF_BYTERUN1, | 237 CODEC_ID_IFF_BYTERUN1, |
216 sizeof(AVFrame), | 238 sizeof(IffContext), |
217 decode_init, | 239 decode_init, |
218 NULL, | 240 NULL, |
219 decode_end, | 241 decode_end, |
220 decode_frame_byterun1, | 242 decode_frame_byterun1, |
221 CODEC_CAP_DR1, | 243 CODEC_CAP_DR1, |