Mercurial > libavcodec.hg
annotate anm.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | 7dd2a45249a9 |
children |
rev | line source |
---|---|
10835 | 1 /* |
2 * Deluxe Paint Animation decoder | |
3 * Copyright (c) 2009 Peter Ross | |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
23 * @file |
10835 | 24 * Deluxe Paint Animation decoder |
25 */ | |
26 | |
27 #include "avcodec.h" | |
28 #include "bytestream.h" | |
29 | |
30 typedef struct AnmContext { | |
31 AVFrame frame; | |
32 int x; ///< x coordinate position | |
33 } AnmContext; | |
34 | |
35 static av_cold int decode_init(AVCodecContext *avctx) | |
36 { | |
37 AnmContext *s = avctx->priv_data; | |
38 const uint8_t *buf; | |
39 int i; | |
40 | |
41 avctx->pix_fmt = PIX_FMT_PAL8; | |
42 | |
43 if (avctx->extradata_size != 16*8 + 4*256) | |
44 return -1; | |
45 | |
46 s->frame.reference = 1; | |
47 if (avctx->get_buffer(avctx, &s->frame) < 0) { | |
48 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
49 return -1; | |
50 } | |
51 | |
52 buf = avctx->extradata + 16*8; | |
53 for (i = 0; i < 256; i++) | |
54 ((uint32_t*)s->frame.data[1])[i] = bytestream_get_le32(&buf); | |
55 | |
56 return 0; | |
57 } | |
58 | |
59 /** | |
60 * Perform decode operation | |
61 * @param dst, dst_end Destination image buffer | |
62 * @param buf, buf_end Source buffer (optional, see below) | |
63 * @param pixel Fill color (optional, see below) | |
64 * @param count Pixel count | |
65 * @param x Pointer to x-axis counter | |
66 * @param width Image width | |
67 * @param linesize Destination image buffer linesize | |
68 * @return non-zero if destination buffer is exhausted | |
69 * | |
70 * a copy operation is achieved when 'buf' is set | |
71 * a fill operation is acheived when 'buf' is null and pixel is >= 0 | |
72 * a skip operation is acheived when 'buf' is null and pixel is < 0 | |
73 */ | |
74 static inline int op(uint8_t **dst, const uint8_t *dst_end, | |
75 const uint8_t **buf, const uint8_t *buf_end, | |
76 int pixel, int count, | |
77 int *x, int width, int linesize) | |
78 { | |
79 int remaining = width - *x; | |
80 while(count > 0) { | |
81 int striplen = FFMIN(count, remaining); | |
82 if (buf) { | |
83 striplen = FFMIN(striplen, buf_end - *buf); | |
84 memcpy(*dst, *buf, striplen); | |
85 *buf += striplen; | |
86 } else if (pixel >= 0) | |
87 memset(*dst, pixel, striplen); | |
88 *dst += striplen; | |
89 remaining -= striplen; | |
90 count -= striplen; | |
91 if (remaining <= 0) { | |
92 *dst += linesize - width; | |
93 remaining = width; | |
94 } | |
95 if (linesize > 0) { | |
96 if (*dst >= dst_end) goto exhausted; | |
97 } else { | |
98 if (*dst <= dst_end) goto exhausted; | |
99 } | |
100 } | |
101 *x = width - remaining; | |
102 return 0; | |
103 | |
104 exhausted: | |
105 *x = width - remaining; | |
106 return 1; | |
107 } | |
108 | |
109 static int decode_frame(AVCodecContext *avctx, | |
110 void *data, int *data_size, | |
111 AVPacket *avpkt) | |
112 { | |
113 AnmContext *s = avctx->priv_data; | |
114 const uint8_t *buf = avpkt->data; | |
115 const int buf_size = avpkt->size; | |
116 const uint8_t *buf_end = buf + buf_size; | |
117 uint8_t *dst, *dst_end; | |
118 int count; | |
119 | |
120 if(avctx->reget_buffer(avctx, &s->frame) < 0){ | |
121 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
122 return -1; | |
123 } | |
124 dst = s->frame.data[0]; | |
125 dst_end = s->frame.data[0] + s->frame.linesize[0]*avctx->height; | |
126 | |
127 if (buf[0] != 0x42) { | |
128 av_log_ask_for_sample(avctx, "unknown record type\n"); | |
129 return buf_size; | |
130 } | |
131 if (buf[1]) { | |
132 av_log_ask_for_sample(avctx, "padding bytes not supported\n"); | |
133 return buf_size; | |
134 } | |
135 buf += 4; | |
136 | |
137 s->x = 0; | |
138 do { | |
139 /* if statements are ordered by probability */ | |
140 #define OP(buf, pixel, count) \ | |
141 op(&dst, dst_end, (buf), buf_end, (pixel), (count), &s->x, avctx->width, s->frame.linesize[0]) | |
142 | |
143 int type = bytestream_get_byte(&buf); | |
144 count = type & 0x7F; | |
145 type >>= 7; | |
146 if (count) { | |
147 if (OP(type ? NULL : &buf, -1, count)) break; | |
148 } else if (!type) { | |
149 int pixel; | |
150 count = bytestream_get_byte(&buf); /* count==0 gives nop */ | |
151 pixel = bytestream_get_byte(&buf); | |
152 if (OP(NULL, pixel, count)) break; | |
153 } else { | |
154 int pixel; | |
155 type = bytestream_get_le16(&buf); | |
156 count = type & 0x3FFF; | |
157 type >>= 14; | |
158 if (!count) { | |
159 if (type == 0) | |
160 break; // stop | |
161 if (type == 2) { | |
162 av_log_ask_for_sample(avctx, "unknown opcode"); | |
163 return AVERROR_INVALIDDATA; | |
164 } | |
165 continue; | |
166 } | |
167 pixel = type == 3 ? bytestream_get_byte(&buf) : -1; | |
168 if (type == 1) count += 0x4000; | |
169 if (OP(type == 2 ? &buf : NULL, pixel, count)) break; | |
170 } | |
171 } while (buf + 1 < buf_end); | |
172 | |
173 *data_size = sizeof(AVFrame); | |
174 *(AVFrame*)data = s->frame; | |
175 return buf_size; | |
176 } | |
177 | |
178 static av_cold int decode_end(AVCodecContext *avctx) | |
179 { | |
180 AnmContext *s = avctx->priv_data; | |
181 if (s->frame.data[0]) | |
182 avctx->release_buffer(avctx, &s->frame); | |
183 return 0; | |
184 } | |
185 | |
186 AVCodec anm_decoder = { | |
187 "anm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10835
diff
changeset
|
188 AVMEDIA_TYPE_VIDEO, |
10835 | 189 CODEC_ID_ANM, |
190 sizeof(AnmContext), | |
191 decode_init, | |
192 NULL, | |
193 decode_end, | |
194 decode_frame, | |
195 CODEC_CAP_DR1, | |
196 .long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), | |
197 }; |