Revision 005caa34
libavcodec/iff.c | ||
---|---|---|
26 | 26 |
|
27 | 27 |
#include "bytestream.h" |
28 | 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 | 38 |
* Convert CMAP buffer (stored in extradata) to lavc palette format |
... | ... | |
45 | 52 |
return AVERROR_INVALIDDATA; |
46 | 53 |
} |
47 | 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 | 57 |
return 0; |
51 | 58 |
} |
52 | 59 |
|
53 | 60 |
static av_cold int decode_init(AVCodecContext *avctx) |
54 | 61 |
{ |
55 |
AVFrame *frame = avctx->priv_data; |
|
62 |
IffContext *s = avctx->priv_data; |
|
63 |
|
|
64 |
if (avctx->bits_per_coded_sample <= 8) { |
|
65 |
avctx->pix_fmt = PIX_FMT_PAL8; |
|
66 |
} else if (avctx->bits_per_coded_sample <= 32) { |
|
67 |
avctx->pix_fmt = PIX_FMT_BGR32; |
|
68 |
} else { |
|
69 |
return AVERROR_INVALIDDATA; |
|
70 |
} |
|
56 | 71 |
|
57 |
avctx->pix_fmt = PIX_FMT_PAL8; |
|
58 |
frame->reference = 1; |
|
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); |
|
59 | 76 |
|
60 |
if (avctx->get_buffer(avctx, frame) < 0) { |
|
77 |
s->frame.reference = 1; |
|
78 |
if (avctx->get_buffer(avctx, &s->frame) < 0) { |
|
61 | 79 |
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
62 | 80 |
return AVERROR_UNKNOWN; |
63 | 81 |
} |
64 |
return ff_cmap_read_palette(avctx, (uint32_t*)frame->data[1]); |
|
65 |
} |
|
66 | 82 |
|
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 |
} |
|
83 |
return avctx->bits_per_coded_sample <= 8 ? |
|
84 |
ff_cmap_read_palette(avctx, (uint32_t*)s->frame.data[1]) : 0; |
|
80 | 85 |
} |
81 | 86 |
|
82 | 87 |
/** |
83 |
* Interleaved memset |
|
88 |
* Decode interleaved plane buffer |
|
89 |
* @param dst Destination buffer |
|
90 |
* @param buf Source buffer |
|
91 |
* @param buf_size |
|
92 |
* @param bps bits_per_coded_sample |
|
93 |
* @param plane plane number to decode as |
|
84 | 94 |
*/ |
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 |
} |
|
95 |
#define DECLARE_DECODEPLANE(suffix, type) \ |
|
96 |
static void decodeplane##suffix(void *dst, const uint8_t const *buf, int buf_size, int bps, int plane) \ |
|
97 |
{ \ |
|
98 |
GetBitContext gb; \ |
|
99 |
int i, b; \ |
|
100 |
init_get_bits(&gb, buf, buf_size * 8); \ |
|
101 |
for(i = 0; i < (buf_size * 8 + bps - 1) / bps; i++) { \ |
|
102 |
for (b = 0; b < bps; b++) { \ |
|
103 |
((type *)dst)[ i*bps + b ] |= get_bits1(&gb) << plane; \ |
|
104 |
} \ |
|
105 |
} \ |
|
94 | 106 |
} |
107 |
DECLARE_DECODEPLANE(8, uint8_t) |
|
108 |
DECLARE_DECODEPLANE(32, uint32_t) |
|
95 | 109 |
|
96 | 110 |
static int decode_frame_ilbm(AVCodecContext *avctx, |
97 | 111 |
void *data, int *data_size, |
98 | 112 |
AVPacket *avpkt) |
99 | 113 |
{ |
100 |
AVFrame *frame = avctx->priv_data;
|
|
114 |
IffContext *s = avctx->priv_data;
|
|
101 | 115 |
const uint8_t *buf = avpkt->data; |
102 | 116 |
int buf_size = avpkt->size; |
103 |
int planewidth = avctx->width / avctx->bits_per_coded_sample; |
|
104 | 117 |
int y, plane; |
105 | 118 |
|
106 |
if (avctx->reget_buffer(avctx, frame) < 0){ |
|
119 |
if (avctx->reget_buffer(avctx, &s->frame) < 0){
|
|
107 | 120 |
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
108 | 121 |
return -1; |
109 | 122 |
} |
... | ... | |
114 | 127 |
} |
115 | 128 |
|
116 | 129 |
for(y = 0; y < avctx->height; y++ ) { |
117 |
uint8_t *row = &frame->data[0][ y*frame->linesize[0] ];
|
|
118 |
memset(row, 0, avctx->width);
|
|
130 |
uint8_t *row = &s->frame.data[0][ y*s->frame.linesize[0] ];
|
|
131 |
memset(row, 0, avctx->pix_fmt == PIX_FMT_PAL8 ? avctx->width : (avctx->width * 4));
|
|
119 | 132 |
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; |
|
133 |
if (avctx->pix_fmt == PIX_FMT_PAL8) { |
|
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 | 142 |
*data_size = sizeof(AVFrame); |
126 |
*(AVFrame*)data = *frame;
|
|
143 |
*(AVFrame*)data = s->frame;
|
|
127 | 144 |
return buf_size; |
128 | 145 |
} |
129 | 146 |
|
... | ... | |
131 | 148 |
void *data, int *data_size, |
132 | 149 |
AVPacket *avpkt) |
133 | 150 |
{ |
134 |
AVFrame *frame = avctx->priv_data;
|
|
151 |
IffContext *s = avctx->priv_data;
|
|
135 | 152 |
const uint8_t *buf = avpkt->data; |
136 | 153 |
int buf_size = avpkt->size; |
137 | 154 |
const uint8_t *buf_end = buf+buf_size; |
138 |
int planewidth = avctx->width / avctx->bits_per_coded_sample; |
|
139 | 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 | 158 |
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
143 | 159 |
return -1; |
144 | 160 |
} |
145 | 161 |
|
146 | 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 | 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 | 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 | 168 |
int8_t value = *buf++; |
153 | 169 |
int length; |
154 | 170 |
if (value >= 0) { |
155 | 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 | 173 |
buf += length; |
158 | 174 |
} else if (value > -128) { |
159 | 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 | 177 |
} else { //noop |
162 | 178 |
continue; |
163 | 179 |
} |
164 | 180 |
x += length; |
165 | 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); |
|
186 |
} |
|
166 | 187 |
} |
167 | 188 |
} else { |
168 | 189 |
for(x = 0; x < avctx->width && buf < buf_end; ) { |
... | ... | |
184 | 205 |
} |
185 | 206 |
|
186 | 207 |
*data_size = sizeof(AVFrame); |
187 |
*(AVFrame*)data = *frame;
|
|
208 |
*(AVFrame*)data = s->frame;
|
|
188 | 209 |
return buf_size; |
189 | 210 |
} |
190 | 211 |
|
191 | 212 |
static av_cold int decode_end(AVCodecContext *avctx) |
192 | 213 |
{ |
193 |
AVFrame *frame = avctx->priv_data; |
|
194 |
if (frame->data[0]) |
|
195 |
avctx->release_buffer(avctx, frame); |
|
214 |
IffContext *s = avctx->priv_data; |
|
215 |
if (s->frame.data[0]) |
|
216 |
avctx->release_buffer(avctx, &s->frame); |
|
217 |
av_freep(&s->planebuf); |
|
196 | 218 |
return 0; |
197 | 219 |
} |
198 | 220 |
|
... | ... | |
200 | 222 |
"iff_ilbm", |
201 | 223 |
CODEC_TYPE_VIDEO, |
202 | 224 |
CODEC_ID_IFF_ILBM, |
203 |
sizeof(AVFrame),
|
|
225 |
sizeof(IffContext),
|
|
204 | 226 |
decode_init, |
205 | 227 |
NULL, |
206 | 228 |
decode_end, |
... | ... | |
213 | 235 |
"iff_byterun1", |
214 | 236 |
CODEC_TYPE_VIDEO, |
215 | 237 |
CODEC_ID_IFF_BYTERUN1, |
216 |
sizeof(AVFrame),
|
|
238 |
sizeof(IffContext),
|
|
217 | 239 |
decode_init, |
218 | 240 |
NULL, |
219 | 241 |
decode_end, |
Also available in: Unified diff