Mercurial > libavcodec.hg
annotate c93.c @ 6920:d02af7474bff libavcodec
Prevent 128*1<<trellis from becoming 0 and creating 0 sized arrays.
fixes CID84 RUN2
CID85 RUN2
CID86 RUN2
CID87 RUN2
CID88 RUN2
CID89 RUN2
CID90 RUN2
CID91 RUN2
CID92 RUN2
CID93 RUN2
CID94 RUN2
CID95 RUN2
CID96 RUN2
CID97 RUN2
CID98 RUN2
CID99 RUN2
CID100 RUN2
CID101 RUN2
CID102 RUN2
CID103 RUN2
CID104 RUN2
CID105 RUN2
CID106 RUN2
author | michael |
---|---|
date | Wed, 28 May 2008 11:59:41 +0000 |
parents | a4104482ceef |
children | e943e1409077 |
rev | line source |
---|---|
4797 | 1 /* |
2 * Interplay C93 video decoder | |
3 * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | |
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 | |
5215 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
4797 | 20 */ |
21 | |
22 #include "avcodec.h" | |
23 #include "bytestream.h" | |
24 | |
25 typedef struct { | |
26 AVFrame pictures[2]; | |
27 int currentpic; | |
28 } C93DecoderContext; | |
29 | |
30 typedef enum { | |
31 C93_8X8_FROM_PREV = 0x02, | |
32 C93_4X4_FROM_PREV = 0x06, | |
33 C93_4X4_FROM_CURR = 0x07, | |
34 C93_8X8_2COLOR = 0x08, | |
35 C93_4X4_2COLOR = 0x0A, | |
36 C93_4X4_4COLOR_GRP = 0x0B, | |
37 C93_4X4_4COLOR = 0x0D, | |
38 C93_NOOP = 0x0E, | |
39 C93_8X8_INTRA = 0x0F, | |
40 } C93BlockType; | |
41 | |
42 #define WIDTH 320 | |
43 #define HEIGHT 192 | |
44 | |
45 #define C93_HAS_PALETTE 0x01 | |
46 #define C93_FIRST_FRAME 0x02 | |
47 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6227
diff
changeset
|
48 static av_cold int decode_init(AVCodecContext *avctx) |
4797 | 49 { |
50 avctx->pix_fmt = PIX_FMT_PAL8; | |
51 return 0; | |
52 } | |
53 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6227
diff
changeset
|
54 static av_cold int decode_end(AVCodecContext *avctx) |
4797 | 55 { |
56 C93DecoderContext * const c93 = avctx->priv_data; | |
57 | |
58 if (c93->pictures[0].data[0]) | |
59 avctx->release_buffer(avctx, &c93->pictures[0]); | |
60 if (c93->pictures[1].data[0]) | |
61 avctx->release_buffer(avctx, &c93->pictures[1]); | |
62 return 0; | |
63 } | |
64 | |
4819 | 65 static inline int copy_block(AVCodecContext *avctx, uint8_t *to, |
4797 | 66 uint8_t *from, int offset, int height, int stride) |
67 { | |
68 int i; | |
69 int width = height; | |
70 int from_x = offset % WIDTH; | |
71 int from_y = offset / WIDTH; | |
72 int overflow = from_x + width - WIDTH; | |
73 | |
74 if (!from) { | |
75 /* silently ignoring predictive blocks in first frame */ | |
76 return 0; | |
77 } | |
78 | |
79 if (from_y + height > HEIGHT) { | |
80 av_log(avctx, AV_LOG_ERROR, "invalid offset %d during C93 decoding\n", | |
81 offset); | |
82 return -1; | |
83 } | |
84 | |
85 if (overflow > 0) { | |
86 width -= overflow; | |
87 for (i = 0; i < height; i++) { | |
88 memcpy(&to[i*stride+width], &from[(from_y+i)*stride], overflow); | |
89 } | |
90 } | |
91 | |
92 for (i = 0; i < height; i++) { | |
93 memcpy(&to[i*stride], &from[(from_y+i)*stride+from_x], width); | |
94 } | |
95 | |
96 return 0; | |
97 } | |
98 | |
4819 | 99 static inline void draw_n_color(uint8_t *out, int stride, int width, |
4797 | 100 int height, int bpp, uint8_t cols[4], uint8_t grps[4], uint32_t col) |
101 { | |
102 int x, y; | |
103 for (y = 0; y < height; y++) { | |
104 if (grps) | |
105 cols[0] = grps[3 * (y >> 1)]; | |
106 for (x = 0; x < width; x++) { | |
107 if (grps) | |
108 cols[1]= grps[(x >> 1) + 1]; | |
109 out[x + y*stride] = cols[col & ((1 << bpp) - 1)]; | |
110 col >>= bpp; | |
111 } | |
112 } | |
113 } | |
114 | |
4819 | 115 static int decode_frame(AVCodecContext *avctx, void *data, |
6227 | 116 int *data_size, const uint8_t * buf, int buf_size) |
4797 | 117 { |
118 C93DecoderContext * const c93 = avctx->priv_data; | |
119 AVFrame * const newpic = &c93->pictures[c93->currentpic]; | |
120 AVFrame * const oldpic = &c93->pictures[c93->currentpic^1]; | |
121 AVFrame *picture = data; | |
122 uint8_t *out; | |
4820 | 123 int stride, i, x, y, bt = 0; |
4797 | 124 |
125 c93->currentpic ^= 1; | |
126 | |
127 newpic->reference = 1; | |
128 newpic->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | | |
129 FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE; | |
130 if (avctx->reget_buffer(avctx, newpic)) { | |
131 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
132 return -1; | |
133 } | |
134 | |
135 stride = newpic->linesize[0]; | |
136 | |
137 if (buf[0] & C93_FIRST_FRAME) { | |
138 newpic->pict_type = FF_I_TYPE; | |
139 newpic->key_frame = 1; | |
140 } else { | |
141 newpic->pict_type = FF_P_TYPE; | |
142 newpic->key_frame = 0; | |
143 } | |
144 | |
145 if (*buf++ & C93_HAS_PALETTE) { | |
146 uint32_t *palette = (uint32_t *) newpic->data[1]; | |
6227 | 147 const uint8_t *palbuf = buf + buf_size - 768 - 1; |
4797 | 148 for (i = 0; i < 256; i++) { |
149 palette[i] = bytestream_get_be24(&palbuf); | |
150 } | |
151 } else { | |
152 if (oldpic->data[1]) | |
153 memcpy(newpic->data[1], oldpic->data[1], 256 * 4); | |
154 } | |
155 | |
156 for (y = 0; y < HEIGHT; y += 8) { | |
157 out = newpic->data[0] + y * stride; | |
158 for (x = 0; x < WIDTH; x += 8) { | |
159 uint8_t *copy_from = oldpic->data[0]; | |
160 unsigned int offset, j; | |
161 uint8_t cols[4], grps[4]; | |
4820 | 162 C93BlockType block_type; |
4797 | 163 |
164 if (!bt) | |
165 bt = *buf++; | |
166 | |
4820 | 167 block_type= bt & 0x0F; |
168 switch (block_type) { | |
4797 | 169 case C93_8X8_FROM_PREV: |
170 offset = bytestream_get_le16(&buf); | |
4819 | 171 if (copy_block(avctx, out, copy_from, offset, 8, stride)) |
4797 | 172 return -1; |
173 break; | |
174 | |
175 case C93_4X4_FROM_CURR: | |
176 copy_from = newpic->data[0]; | |
177 case C93_4X4_FROM_PREV: | |
178 for (j = 0; j < 8; j += 4) { | |
179 for (i = 0; i < 8; i += 4) { | |
180 offset = bytestream_get_le16(&buf); | |
4819 | 181 if (copy_block(avctx, &out[j*stride+i], |
4797 | 182 copy_from, offset, 4, stride)) |
183 return -1; | |
184 } | |
185 } | |
186 break; | |
187 | |
188 case C93_8X8_2COLOR: | |
189 bytestream_get_buffer(&buf, cols, 2); | |
190 for (i = 0; i < 8; i++) { | |
4819 | 191 draw_n_color(out + i*stride, stride, 8, 1, 1, cols, |
4797 | 192 NULL, *buf++); |
193 } | |
194 | |
195 break; | |
196 | |
197 case C93_4X4_2COLOR: | |
198 case C93_4X4_4COLOR: | |
199 case C93_4X4_4COLOR_GRP: | |
200 for (j = 0; j < 8; j += 4) { | |
201 for (i = 0; i < 8; i += 4) { | |
4820 | 202 if (block_type == C93_4X4_2COLOR) { |
4797 | 203 bytestream_get_buffer(&buf, cols, 2); |
4819 | 204 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 205 1, cols, NULL, bytestream_get_le16(&buf)); |
4820 | 206 } else if (block_type == C93_4X4_4COLOR) { |
4797 | 207 bytestream_get_buffer(&buf, cols, 4); |
4819 | 208 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 209 2, cols, NULL, bytestream_get_le32(&buf)); |
210 } else { | |
211 bytestream_get_buffer(&buf, grps, 4); | |
4819 | 212 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 213 1, cols, grps, bytestream_get_le16(&buf)); |
214 } | |
215 } | |
216 } | |
217 break; | |
218 | |
219 case C93_NOOP: | |
220 break; | |
221 | |
222 case C93_8X8_INTRA: | |
223 for (j = 0; j < 8; j++) | |
224 bytestream_get_buffer(&buf, out + j*stride, 8); | |
225 break; | |
226 | |
227 default: | |
228 av_log(avctx, AV_LOG_ERROR, "unexpected type %x at %dx%d\n", | |
4820 | 229 block_type, x, y); |
4797 | 230 return -1; |
231 } | |
232 bt >>= 4; | |
233 out += 8; | |
234 } | |
235 } | |
236 | |
237 *picture = *newpic; | |
238 *data_size = sizeof(AVFrame); | |
239 | |
240 return buf_size; | |
241 } | |
242 | |
243 AVCodec c93_decoder = { | |
244 "c93", | |
245 CODEC_TYPE_VIDEO, | |
246 CODEC_ID_C93, | |
247 sizeof(C93DecoderContext), | |
4819 | 248 decode_init, |
4797 | 249 NULL, |
4819 | 250 decode_end, |
251 decode_frame, | |
4797 | 252 CODEC_CAP_DR1, |
6710 | 253 .long_name = "Interplay C93", |
4797 | 254 }; |