Mercurial > libavcodec.hg
annotate c93.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 8a4984c5cacc |
children |
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, |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
116 int *data_size, AVPacket *avpkt) |
4797 | 117 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
118 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
7040
diff
changeset
|
119 int buf_size = avpkt->size; |
4797 | 120 C93DecoderContext * const c93 = avctx->priv_data; |
121 AVFrame * const newpic = &c93->pictures[c93->currentpic]; | |
122 AVFrame * const oldpic = &c93->pictures[c93->currentpic^1]; | |
123 AVFrame *picture = data; | |
124 uint8_t *out; | |
4820 | 125 int stride, i, x, y, bt = 0; |
4797 | 126 |
127 c93->currentpic ^= 1; | |
128 | |
129 newpic->reference = 1; | |
130 newpic->buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | | |
131 FF_BUFFER_HINTS_REUSABLE | FF_BUFFER_HINTS_READABLE; | |
132 if (avctx->reget_buffer(avctx, newpic)) { | |
133 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); | |
134 return -1; | |
135 } | |
136 | |
137 stride = newpic->linesize[0]; | |
138 | |
139 if (buf[0] & C93_FIRST_FRAME) { | |
140 newpic->pict_type = FF_I_TYPE; | |
141 newpic->key_frame = 1; | |
142 } else { | |
143 newpic->pict_type = FF_P_TYPE; | |
144 newpic->key_frame = 0; | |
145 } | |
146 | |
147 if (*buf++ & C93_HAS_PALETTE) { | |
148 uint32_t *palette = (uint32_t *) newpic->data[1]; | |
6227 | 149 const uint8_t *palbuf = buf + buf_size - 768 - 1; |
4797 | 150 for (i = 0; i < 256; i++) { |
151 palette[i] = bytestream_get_be24(&palbuf); | |
152 } | |
153 } else { | |
154 if (oldpic->data[1]) | |
155 memcpy(newpic->data[1], oldpic->data[1], 256 * 4); | |
156 } | |
157 | |
158 for (y = 0; y < HEIGHT; y += 8) { | |
159 out = newpic->data[0] + y * stride; | |
160 for (x = 0; x < WIDTH; x += 8) { | |
161 uint8_t *copy_from = oldpic->data[0]; | |
162 unsigned int offset, j; | |
163 uint8_t cols[4], grps[4]; | |
4820 | 164 C93BlockType block_type; |
4797 | 165 |
166 if (!bt) | |
167 bt = *buf++; | |
168 | |
4820 | 169 block_type= bt & 0x0F; |
170 switch (block_type) { | |
4797 | 171 case C93_8X8_FROM_PREV: |
172 offset = bytestream_get_le16(&buf); | |
4819 | 173 if (copy_block(avctx, out, copy_from, offset, 8, stride)) |
4797 | 174 return -1; |
175 break; | |
176 | |
177 case C93_4X4_FROM_CURR: | |
178 copy_from = newpic->data[0]; | |
179 case C93_4X4_FROM_PREV: | |
180 for (j = 0; j < 8; j += 4) { | |
181 for (i = 0; i < 8; i += 4) { | |
182 offset = bytestream_get_le16(&buf); | |
4819 | 183 if (copy_block(avctx, &out[j*stride+i], |
4797 | 184 copy_from, offset, 4, stride)) |
185 return -1; | |
186 } | |
187 } | |
188 break; | |
189 | |
190 case C93_8X8_2COLOR: | |
191 bytestream_get_buffer(&buf, cols, 2); | |
192 for (i = 0; i < 8; i++) { | |
4819 | 193 draw_n_color(out + i*stride, stride, 8, 1, 1, cols, |
4797 | 194 NULL, *buf++); |
195 } | |
196 | |
197 break; | |
198 | |
199 case C93_4X4_2COLOR: | |
200 case C93_4X4_4COLOR: | |
201 case C93_4X4_4COLOR_GRP: | |
202 for (j = 0; j < 8; j += 4) { | |
203 for (i = 0; i < 8; i += 4) { | |
4820 | 204 if (block_type == C93_4X4_2COLOR) { |
4797 | 205 bytestream_get_buffer(&buf, cols, 2); |
4819 | 206 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 207 1, cols, NULL, bytestream_get_le16(&buf)); |
4820 | 208 } else if (block_type == C93_4X4_4COLOR) { |
4797 | 209 bytestream_get_buffer(&buf, cols, 4); |
4819 | 210 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 211 2, cols, NULL, bytestream_get_le32(&buf)); |
212 } else { | |
213 bytestream_get_buffer(&buf, grps, 4); | |
4819 | 214 draw_n_color(out + i + j*stride, stride, 4, 4, |
4797 | 215 1, cols, grps, bytestream_get_le16(&buf)); |
216 } | |
217 } | |
218 } | |
219 break; | |
220 | |
221 case C93_NOOP: | |
222 break; | |
223 | |
224 case C93_8X8_INTRA: | |
225 for (j = 0; j < 8; j++) | |
226 bytestream_get_buffer(&buf, out + j*stride, 8); | |
227 break; | |
228 | |
229 default: | |
230 av_log(avctx, AV_LOG_ERROR, "unexpected type %x at %dx%d\n", | |
4820 | 231 block_type, x, y); |
4797 | 232 return -1; |
233 } | |
234 bt >>= 4; | |
235 out += 8; | |
236 } | |
237 } | |
238 | |
239 *picture = *newpic; | |
240 *data_size = sizeof(AVFrame); | |
241 | |
242 return buf_size; | |
243 } | |
244 | |
245 AVCodec c93_decoder = { | |
246 "c93", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
9355
diff
changeset
|
247 AVMEDIA_TYPE_VIDEO, |
4797 | 248 CODEC_ID_C93, |
249 sizeof(C93DecoderContext), | |
4819 | 250 decode_init, |
4797 | 251 NULL, |
4819 | 252 decode_end, |
253 decode_frame, | |
4797 | 254 CODEC_CAP_DR1, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
255 .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), |
4797 | 256 }; |