Originally committed as revision 5189 to svn://svn.ffmpeg.org/ffmpeg/trunk
Kostya Shishkov authored on 2006/03/22 02:27:47... | ... |
@@ -702,6 +702,8 @@ library: |
702 | 702 |
@tab Multimedia format used in games like Mad Dog McCree |
703 | 703 |
@item AVS @tab @tab X |
704 | 704 |
@tab Multimedia format used by the Creature Shock game. |
705 |
+@item Smacker @tab @tab X |
|
706 |
+@tab Multimedia format used by many games. |
|
705 | 707 |
@end multitable |
706 | 708 |
|
707 | 709 |
@code{X} means that encoding (resp. decoding) is supported. |
... | ... |
@@ -796,6 +798,7 @@ following image formats are supported: |
796 | 796 |
@item American Laser Games Video @tab @tab X @tab Used in games like Mad Dog McCree |
797 | 797 |
@item ZMBV @tab @tab X @tab |
798 | 798 |
@item AVS Video @tab @tab X @tab Video encoding used by the Creature Shock game. |
799 |
+@item Smacker Video @tab @tab X @tab Video encoding used in Smacker. |
|
799 | 800 |
@end multitable |
800 | 801 |
|
801 | 802 |
@code{X} means that encoding (resp. decoding) is supported. |
... | ... |
@@ -871,6 +874,7 @@ other implementations. |
871 | 871 |
@tab All versions except 5.1 are supported |
872 | 872 |
@item DSP Group TrueSpeech @tab @tab X |
873 | 873 |
@item True Audio (TTA) @tab @tab X |
874 |
+@item Smacker Audio @tab @tab X |
|
874 | 875 |
@end multitable |
875 | 876 |
|
876 | 877 |
@code{X} means that encoding (resp. decoding) is supported. |
... | ... |
@@ -447,6 +447,12 @@ void avcodec_register_all(void) |
447 | 447 |
#ifdef CONFIG_ZMBV_DECODER |
448 | 448 |
register_avcodec(&zmbv_decoder); |
449 | 449 |
#endif //CONFIG_ZMBV_DECODER |
450 |
+#ifdef CONFIG_SMACKER_DECODER |
|
451 |
+ register_avcodec(&smacker_decoder); |
|
452 |
+#endif //CONFIG_SMACKER_DECODER |
|
453 |
+#ifdef CONFIG_SMACKAUD_DECODER |
|
454 |
+ register_avcodec(&smackaud_decoder); |
|
455 |
+#endif //CONFIG_SMACKAUD_DECODER |
|
450 | 456 |
#ifdef CONFIG_SONIC_DECODER |
451 | 457 |
register_avcodec(&sonic_decoder); |
452 | 458 |
#endif //CONFIG_SONIC_DECODER |
... | ... |
@@ -21,8 +21,8 @@ extern "C" { |
21 | 21 |
#define AV_STRINGIFY(s) AV_TOSTRING(s) |
22 | 22 |
#define AV_TOSTRING(s) #s |
23 | 23 |
|
24 |
-#define LIBAVCODEC_VERSION_INT ((51<<16)+(7<<8)+0) |
|
25 |
-#define LIBAVCODEC_VERSION 51.7.0 |
|
24 |
+#define LIBAVCODEC_VERSION_INT ((51<<16)+(8<<8)+0) |
|
25 |
+#define LIBAVCODEC_VERSION 51.8.0 |
|
26 | 26 |
#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT |
27 | 27 |
|
28 | 28 |
#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) |
... | ... |
@@ -118,6 +118,7 @@ enum CodecID { |
118 | 118 |
CODEC_ID_MMVIDEO, |
119 | 119 |
CODEC_ID_ZMBV, |
120 | 120 |
CODEC_ID_AVS, |
121 |
+ CODEC_ID_SMACKVIDEO, |
|
121 | 122 |
|
122 | 123 |
/* various pcm "codecs" */ |
123 | 124 |
CODEC_ID_PCM_S16LE= 0x10000, |
... | ... |
@@ -198,6 +199,7 @@ enum CodecID { |
198 | 198 |
CODEC_ID_COOK, |
199 | 199 |
CODEC_ID_TRUESPEECH, |
200 | 200 |
CODEC_ID_TTA, |
201 |
+ CODEC_ID_SMACKAUDIO, |
|
201 | 202 |
|
202 | 203 |
CODEC_ID_OGGTHEORA= 0x16000, |
203 | 204 |
|
... | ... |
@@ -2238,6 +2240,8 @@ extern AVCodec bmp_decoder; |
2238 | 2238 |
extern AVCodec mmvideo_decoder; |
2239 | 2239 |
extern AVCodec zmbv_decoder; |
2240 | 2240 |
extern AVCodec avs_decoder; |
2241 |
+extern AVCodec smacker_decoder; |
|
2242 |
+extern AVCodec smackaud_decoder; |
|
2241 | 2243 |
|
2242 | 2244 |
/* pcm codecs */ |
2243 | 2245 |
#define PCM_CODEC(id, name) \ |
2244 | 2246 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,689 @@ |
0 |
+/* |
|
1 |
+ * Smacker decoder |
|
2 |
+ * Copyright (c) 2006 Konstantin Shishkov |
|
3 |
+ * |
|
4 |
+ * This library is free software; you can redistribute it and/or |
|
5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
6 |
+ * License as published by the Free Software Foundation; either |
|
7 |
+ * version 2 of the License, or (at your option) any later version. |
|
8 |
+ * |
|
9 |
+ * This library is distributed in the hope that it will be useful, |
|
10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 |
+ * Lesser General Public License for more details. |
|
13 |
+ * |
|
14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
15 |
+ * License along with this library; if not, write to the Free Software |
|
16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
17 |
+ * |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+/** |
|
21 |
+ * @file smacker.c |
|
22 |
+ * Smacker decoder |
|
23 |
+ */ |
|
24 |
+ |
|
25 |
+/* |
|
26 |
+ * Based on http://wiki.multimedia.cx/index.php?title=Smacker |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include <stdio.h> |
|
30 |
+#include <stdlib.h> |
|
31 |
+ |
|
32 |
+#include "common.h" |
|
33 |
+#include "avcodec.h" |
|
34 |
+ |
|
35 |
+#define ALT_BITSTREAM_READER_LE |
|
36 |
+#include "bitstream.h" |
|
37 |
+ |
|
38 |
+#define SMKTREE_BITS 9 |
|
39 |
+#define SMK_NODE 0x80000000 |
|
40 |
+ |
|
41 |
+/* |
|
42 |
+ * Decoder context |
|
43 |
+ */ |
|
44 |
+typedef struct SmackVContext { |
|
45 |
+ AVCodecContext *avctx; |
|
46 |
+ AVFrame pic; |
|
47 |
+ |
|
48 |
+ int *mmap_tbl, *mclr_tbl, *full_tbl, *type_tbl; |
|
49 |
+ int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; |
|
50 |
+} SmackVContext; |
|
51 |
+ |
|
52 |
+/** |
|
53 |
+ * Context used for code reconstructing |
|
54 |
+ */ |
|
55 |
+typedef struct HuffContext { |
|
56 |
+ int length; |
|
57 |
+ int maxlength; |
|
58 |
+ int current; |
|
59 |
+ uint32_t *bits; |
|
60 |
+ int *lengths; |
|
61 |
+ int *values; |
|
62 |
+} HuffContext; |
|
63 |
+ |
|
64 |
+/* common parameters used for decode_bigtree */ |
|
65 |
+typedef struct DBCtx { |
|
66 |
+ VLC *v1, *v2; |
|
67 |
+ int *recode1, *recode2; |
|
68 |
+ int escapes[3]; |
|
69 |
+ int *last; |
|
70 |
+ int lcur; |
|
71 |
+} DBCtx; |
|
72 |
+ |
|
73 |
+/* possible runs of blocks */ |
|
74 |
+static const int block_runs[64] = { |
|
75 |
+ 1, 2, 3, 4, 5, 6, 7, 8, |
|
76 |
+ 9, 10, 11, 12, 13, 14, 15, 16, |
|
77 |
+ 17, 18, 19, 20, 21, 22, 23, 24, |
|
78 |
+ 25, 26, 27, 28, 29, 30, 31, 32, |
|
79 |
+ 33, 34, 35, 36, 37, 38, 39, 40, |
|
80 |
+ 41, 42, 43, 44, 45, 46, 47, 48, |
|
81 |
+ 49, 50, 51, 52, 53, 54, 55, 56, |
|
82 |
+ 57, 58, 59, 128, 256, 512, 1024, 2048 }; |
|
83 |
+ |
|
84 |
+enum SmkBlockTypes { |
|
85 |
+ SMK_BLK_MONO = 0, |
|
86 |
+ SMK_BLK_FULL = 1, |
|
87 |
+ SMK_BLK_SKIP = 2, |
|
88 |
+ SMK_BLK_FILL = 3 }; |
|
89 |
+ |
|
90 |
+/** |
|
91 |
+ * Decode local frame tree |
|
92 |
+ */ |
|
93 |
+static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) |
|
94 |
+{ |
|
95 |
+ if(!get_bits1(gb)){ //Leaf |
|
96 |
+ if(hc->current >= 256){ |
|
97 |
+ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); |
|
98 |
+ return -1; |
|
99 |
+ } |
|
100 |
+ if(length){ |
|
101 |
+ hc->bits[hc->current] = prefix; |
|
102 |
+ hc->lengths[hc->current] = length; |
|
103 |
+ } else { |
|
104 |
+ hc->bits[hc->current] = 0; |
|
105 |
+ hc->lengths[hc->current] = 0; |
|
106 |
+ } |
|
107 |
+ hc->values[hc->current] = get_bits(gb, 8); |
|
108 |
+ hc->current++; |
|
109 |
+ if(hc->maxlength < length) |
|
110 |
+ hc->maxlength = length; |
|
111 |
+ return 0; |
|
112 |
+ } else { //Node |
|
113 |
+ int r; |
|
114 |
+ length++; |
|
115 |
+ r = smacker_decode_tree(gb, hc, prefix, length); |
|
116 |
+ if(r) |
|
117 |
+ return r; |
|
118 |
+ return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length); |
|
119 |
+ } |
|
120 |
+} |
|
121 |
+ |
|
122 |
+/** |
|
123 |
+ * Decode header tree |
|
124 |
+ */ |
|
125 |
+static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, DBCtx *ctx) |
|
126 |
+{ |
|
127 |
+ if(!get_bits1(gb)){ //Leaf |
|
128 |
+ int val, i1, i2, b1, b2; |
|
129 |
+ if(hc->current >= hc->length){ |
|
130 |
+ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); |
|
131 |
+ return -1; |
|
132 |
+ } |
|
133 |
+ b1 = get_bits_count(gb); |
|
134 |
+ i1 = get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3); |
|
135 |
+ b1 = get_bits_count(gb) - b1; |
|
136 |
+ b2 = get_bits_count(gb); |
|
137 |
+ i2 = get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3); |
|
138 |
+ b2 = get_bits_count(gb) - b2; |
|
139 |
+ val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); |
|
140 |
+ if(val == ctx->escapes[0]) { |
|
141 |
+ ctx->last[0] = hc->current; |
|
142 |
+ val = 0; |
|
143 |
+ } else if(val == ctx->escapes[1]) { |
|
144 |
+ ctx->last[1] = hc->current; |
|
145 |
+ val = 0; |
|
146 |
+ } else if(val == ctx->escapes[2]) { |
|
147 |
+ ctx->last[2] = hc->current; |
|
148 |
+ val = 0; |
|
149 |
+ } |
|
150 |
+ |
|
151 |
+ hc->values[hc->current++] = val; |
|
152 |
+ return 1; |
|
153 |
+ } else { //Node |
|
154 |
+ int r = 0, t; |
|
155 |
+ |
|
156 |
+ t = hc->current++; |
|
157 |
+ r = smacker_decode_bigtree(gb, hc, ctx); |
|
158 |
+ if(r < 0) |
|
159 |
+ return r; |
|
160 |
+ hc->values[t] = SMK_NODE | r; |
|
161 |
+ r++; |
|
162 |
+ r += smacker_decode_bigtree(gb, hc, ctx); |
|
163 |
+ return r; |
|
164 |
+ } |
|
165 |
+} |
|
166 |
+ |
|
167 |
+/** |
|
168 |
+ * Store large tree as FFmpeg's vlc codes |
|
169 |
+ */ |
|
170 |
+static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) |
|
171 |
+{ |
|
172 |
+ int res; |
|
173 |
+ HuffContext huff; |
|
174 |
+ HuffContext tmp1, tmp2; |
|
175 |
+ VLC vlc[2]; |
|
176 |
+ int escapes[3]; |
|
177 |
+ DBCtx ctx; |
|
178 |
+ |
|
179 |
+ tmp1.length = 256; |
|
180 |
+ tmp1.maxlength = 0; |
|
181 |
+ tmp1.current = 0; |
|
182 |
+ tmp1.bits = av_mallocz(256 * 4); |
|
183 |
+ tmp1.lengths = av_mallocz(256 * sizeof(int)); |
|
184 |
+ tmp1.values = av_mallocz(256 * sizeof(int)); |
|
185 |
+ |
|
186 |
+ tmp2.length = 256; |
|
187 |
+ tmp2.maxlength = 0; |
|
188 |
+ tmp2.current = 0; |
|
189 |
+ tmp2.bits = av_mallocz(256 * 4); |
|
190 |
+ tmp2.lengths = av_mallocz(256 * sizeof(int)); |
|
191 |
+ tmp2.values = av_mallocz(256 * sizeof(int)); |
|
192 |
+ |
|
193 |
+ memset(&vlc[0], 0, sizeof(VLC)); |
|
194 |
+ memset(&vlc[1], 0, sizeof(VLC)); |
|
195 |
+ |
|
196 |
+ if(get_bits1(gb)) { |
|
197 |
+ smacker_decode_tree(gb, &tmp1, 0, 0); |
|
198 |
+ get_bits1(gb); |
|
199 |
+ res = init_vlc(&vlc[0], SMKTREE_BITS, tmp1.length, |
|
200 |
+ tmp1.lengths, sizeof(int), sizeof(int), |
|
201 |
+ tmp1.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); |
|
202 |
+ if(res < 0) { |
|
203 |
+ av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); |
|
204 |
+ return -1; |
|
205 |
+ } |
|
206 |
+ } else { |
|
207 |
+ av_log(smk->avctx, AV_LOG_ERROR, "Skipping low bytes tree\n"); |
|
208 |
+ } |
|
209 |
+ if(get_bits1(gb)){ |
|
210 |
+ smacker_decode_tree(gb, &tmp2, 0, 0); |
|
211 |
+ get_bits1(gb); |
|
212 |
+ res = init_vlc(&vlc[1], SMKTREE_BITS, tmp2.length, |
|
213 |
+ tmp2.lengths, sizeof(int), sizeof(int), |
|
214 |
+ tmp2.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); |
|
215 |
+ if(res < 0) { |
|
216 |
+ av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); |
|
217 |
+ return -1; |
|
218 |
+ } |
|
219 |
+ } else { |
|
220 |
+ av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n"); |
|
221 |
+ } |
|
222 |
+ |
|
223 |
+ escapes[0] = get_bits(gb, 8); |
|
224 |
+ escapes[0] |= get_bits(gb, 8) << 8; |
|
225 |
+ escapes[1] = get_bits(gb, 8); |
|
226 |
+ escapes[1] |= get_bits(gb, 8) << 8; |
|
227 |
+ escapes[2] = get_bits(gb, 8); |
|
228 |
+ escapes[2] |= get_bits(gb, 8) << 8; |
|
229 |
+ |
|
230 |
+ last[0] = last[1] = last[2] = -1; |
|
231 |
+ |
|
232 |
+ ctx.escapes[0] = escapes[0]; |
|
233 |
+ ctx.escapes[1] = escapes[1]; |
|
234 |
+ ctx.escapes[2] = escapes[2]; |
|
235 |
+ ctx.v1 = &vlc[0]; |
|
236 |
+ ctx.v2 = &vlc[1]; |
|
237 |
+ ctx.recode1 = tmp1.values; |
|
238 |
+ ctx.recode2 = tmp2.values; |
|
239 |
+ ctx.last = last; |
|
240 |
+ |
|
241 |
+ huff.length = ((size + 3) >> 2) + 3; |
|
242 |
+ huff.maxlength = 0; |
|
243 |
+ huff.current = 0; |
|
244 |
+ huff.values = av_mallocz(huff.length * sizeof(int)); |
|
245 |
+ |
|
246 |
+ smacker_decode_bigtree(gb, &huff, &ctx); |
|
247 |
+ get_bits1(gb); |
|
248 |
+ if(ctx.last[0] == -1) ctx.last[0] = huff.current++; |
|
249 |
+ if(ctx.last[1] == -1) ctx.last[1] = huff.current++; |
|
250 |
+ if(ctx.last[2] == -1) ctx.last[2] = huff.current++; |
|
251 |
+ |
|
252 |
+ *recodes = huff.values; |
|
253 |
+ |
|
254 |
+ if(vlc[0].table) |
|
255 |
+ free_vlc(&vlc[0]); |
|
256 |
+ if(vlc[1].table) |
|
257 |
+ free_vlc(&vlc[1]); |
|
258 |
+ av_free(tmp1.bits); |
|
259 |
+ av_free(tmp1.lengths); |
|
260 |
+ av_free(tmp1.values); |
|
261 |
+ av_free(tmp2.bits); |
|
262 |
+ av_free(tmp2.lengths); |
|
263 |
+ av_free(tmp2.values); |
|
264 |
+ |
|
265 |
+ return 0; |
|
266 |
+} |
|
267 |
+ |
|
268 |
+static int decode_header_trees(SmackVContext *smk) { |
|
269 |
+ GetBitContext gb; |
|
270 |
+ int mmap_size, mclr_size, full_size, type_size; |
|
271 |
+ |
|
272 |
+ mmap_size = LE_32(smk->avctx->extradata); |
|
273 |
+ mclr_size = LE_32(smk->avctx->extradata + 4); |
|
274 |
+ full_size = LE_32(smk->avctx->extradata + 8); |
|
275 |
+ type_size = LE_32(smk->avctx->extradata + 12); |
|
276 |
+ |
|
277 |
+ init_get_bits(&gb, smk->avctx->extradata + 16, (smk->avctx->extradata_size - 16) * 8); |
|
278 |
+ |
|
279 |
+ if(!get_bits1(&gb)) { |
|
280 |
+ av_log(smk->avctx, AV_LOG_INFO, "Skipping MMAP tree\n"); |
|
281 |
+ smk->mmap_tbl = av_malloc(sizeof(int) * 2); |
|
282 |
+ smk->mmap_tbl[0] = 0; |
|
283 |
+ smk->mmap_last[0] = smk->mmap_last[1] = smk->mmap_last[2] = 1; |
|
284 |
+ } else { |
|
285 |
+ smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size); |
|
286 |
+ } |
|
287 |
+ if(!get_bits(&gb, 1)) { |
|
288 |
+ av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n"); |
|
289 |
+ smk->mclr_tbl = av_malloc(sizeof(int) * 2); |
|
290 |
+ smk->mclr_tbl[0] = 0; |
|
291 |
+ smk->mclr_last[0] = smk->mclr_last[1] = smk->mclr_last[2] = 1; |
|
292 |
+ } else { |
|
293 |
+ smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size); |
|
294 |
+ } |
|
295 |
+ if(!get_bits(&gb, 1)) { |
|
296 |
+ av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n"); |
|
297 |
+ smk->full_tbl = av_malloc(sizeof(int) * 2); |
|
298 |
+ smk->full_tbl[0] = 0; |
|
299 |
+ smk->full_last[0] = smk->full_last[1] = smk->full_last[2] = 1; |
|
300 |
+ } else { |
|
301 |
+ smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size); |
|
302 |
+ } |
|
303 |
+ if(!get_bits(&gb, 1)) { |
|
304 |
+ av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n"); |
|
305 |
+ smk->type_tbl = av_malloc(sizeof(int) * 2); |
|
306 |
+ smk->type_tbl[0] = 0; |
|
307 |
+ smk->type_last[0] = smk->type_last[1] = smk->type_last[2] = 1; |
|
308 |
+ } else { |
|
309 |
+ smacker_decode_header_tree(smk, &gb, &smk->type_tbl, smk->type_last, type_size); |
|
310 |
+ } |
|
311 |
+ |
|
312 |
+ return 0; |
|
313 |
+} |
|
314 |
+ |
|
315 |
+static always_inline void last_reset(int *recode, int *last) { |
|
316 |
+ recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; |
|
317 |
+} |
|
318 |
+ |
|
319 |
+/* get code and update history */ |
|
320 |
+static always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) { |
|
321 |
+ register int *table = recode; |
|
322 |
+ int v, b; |
|
323 |
+ |
|
324 |
+ b = get_bits_count(gb); |
|
325 |
+ while(*table & SMK_NODE) { |
|
326 |
+ if(get_bits1(gb)) |
|
327 |
+ table += (*table) & (~SMK_NODE); |
|
328 |
+ table++; |
|
329 |
+ } |
|
330 |
+ v = *table; |
|
331 |
+ b = get_bits_count(gb) - b; |
|
332 |
+ |
|
333 |
+ if(v != recode[last[0]]) { |
|
334 |
+ recode[last[2]] = recode[last[1]]; |
|
335 |
+ recode[last[1]] = recode[last[0]]; |
|
336 |
+ recode[last[0]] = v; |
|
337 |
+ } |
|
338 |
+ return v; |
|
339 |
+} |
|
340 |
+ |
|
341 |
+static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) |
|
342 |
+{ |
|
343 |
+ SmackVContext * const smk = (SmackVContext *)avctx->priv_data; |
|
344 |
+ uint8_t *out; |
|
345 |
+ uint32_t *pal; |
|
346 |
+ GetBitContext gb; |
|
347 |
+ int blocks, blk, bw, bh; |
|
348 |
+ int i; |
|
349 |
+ int stride; |
|
350 |
+ |
|
351 |
+ if(buf_size == 769) |
|
352 |
+ return 0; |
|
353 |
+ if(smk->pic.data[0]) |
|
354 |
+ avctx->release_buffer(avctx, &smk->pic); |
|
355 |
+ |
|
356 |
+ smk->pic.reference = 1; |
|
357 |
+ smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
|
358 |
+ if(avctx->reget_buffer(avctx, &smk->pic) < 0){ |
|
359 |
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
|
360 |
+ return -1; |
|
361 |
+ } |
|
362 |
+ |
|
363 |
+ /* make the palette available on the way out */ |
|
364 |
+ out = buf + 1; |
|
365 |
+ pal = (uint32_t*)smk->pic.data[1]; |
|
366 |
+ smk->pic.palette_has_changed = buf[0] & 1; |
|
367 |
+ smk->pic.key_frame = !!(buf[0] & 2); |
|
368 |
+ if(smk->pic.key_frame) |
|
369 |
+ smk->pic.pict_type = FF_I_TYPE; |
|
370 |
+ else |
|
371 |
+ smk->pic.pict_type = FF_P_TYPE; |
|
372 |
+ |
|
373 |
+ for(i = 0; i < 256; i++) { |
|
374 |
+ int r, g, b; |
|
375 |
+ r = *out++; |
|
376 |
+ g = *out++; |
|
377 |
+ b = *out++; |
|
378 |
+ *pal++ = (r << 16) | (g << 8) | b; |
|
379 |
+ } |
|
380 |
+ |
|
381 |
+ last_reset(smk->mmap_tbl, smk->mmap_last); |
|
382 |
+ last_reset(smk->mclr_tbl, smk->mclr_last); |
|
383 |
+ last_reset(smk->full_tbl, smk->full_last); |
|
384 |
+ last_reset(smk->type_tbl, smk->type_last); |
|
385 |
+ init_get_bits(&gb, buf + 769, (buf_size - 769) * 8); |
|
386 |
+ |
|
387 |
+ blk = 0; |
|
388 |
+ bw = avctx->width >> 2; |
|
389 |
+ bh = avctx->height >> 2; |
|
390 |
+ blocks = bw * bh; |
|
391 |
+ out = smk->pic.data[0]; |
|
392 |
+ stride = smk->pic.linesize[0]; |
|
393 |
+ while(blk < blocks) { |
|
394 |
+ int type, run, mode; |
|
395 |
+ uint16_t pix; |
|
396 |
+ |
|
397 |
+ type = smk_get_code(&gb, smk->type_tbl, smk->type_last); |
|
398 |
+ run = block_runs[(type >> 2) & 0x3F]; |
|
399 |
+ switch(type & 3){ |
|
400 |
+ case SMK_BLK_MONO: |
|
401 |
+ while(run-- && blk < blocks){ |
|
402 |
+ int clr, map; |
|
403 |
+ int hi, lo; |
|
404 |
+ clr = smk_get_code(&gb, smk->mclr_tbl, smk->mclr_last); |
|
405 |
+ map = smk_get_code(&gb, smk->mmap_tbl, smk->mmap_last); |
|
406 |
+ out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; |
|
407 |
+ hi = clr >> 8; |
|
408 |
+ lo = clr & 0xFF; |
|
409 |
+ for(i = 0; i < 4; i++) { |
|
410 |
+ if(map & 1) out[0] = hi; else out[0] = lo; |
|
411 |
+ if(map & 2) out[1] = hi; else out[1] = lo; |
|
412 |
+ if(map & 4) out[2] = hi; else out[2] = lo; |
|
413 |
+ if(map & 8) out[3] = hi; else out[3] = lo; |
|
414 |
+ map >>= 4; |
|
415 |
+ out += stride; |
|
416 |
+ } |
|
417 |
+ blk++; |
|
418 |
+ } |
|
419 |
+ break; |
|
420 |
+ case SMK_BLK_FULL: |
|
421 |
+ mode = 0; |
|
422 |
+ if(avctx->codec_tag != 0) { // In case of Smacker v4 we have three modes |
|
423 |
+ if(get_bits1(&gb)) mode = 1; |
|
424 |
+ else if(get_bits1(&gb)) mode = 2; |
|
425 |
+ } |
|
426 |
+ while(run-- && blk < blocks){ |
|
427 |
+ out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; |
|
428 |
+ switch(mode){ |
|
429 |
+ case 0: |
|
430 |
+ for(i = 0; i < 4; i++) { |
|
431 |
+ pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
432 |
+ out[2] = pix & 0xFF; |
|
433 |
+ out[3] = pix >> 8; |
|
434 |
+ pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
435 |
+ out[0] = pix & 0xFF; |
|
436 |
+ out[1] = pix >> 8; |
|
437 |
+ out += stride; |
|
438 |
+ } |
|
439 |
+ break; |
|
440 |
+ case 1: |
|
441 |
+ pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
442 |
+ out[0] = out[1] = pix & 0xFF; |
|
443 |
+ out[2] = out[3] = pix >> 8; |
|
444 |
+ out += stride; |
|
445 |
+ out[0] = out[1] = pix & 0xFF; |
|
446 |
+ out[2] = out[3] = pix >> 8; |
|
447 |
+ out += stride; |
|
448 |
+ pix = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
449 |
+ out[0] = out[1] = pix & 0xFF; |
|
450 |
+ out[2] = out[3] = pix >> 8; |
|
451 |
+ out += stride; |
|
452 |
+ out[0] = out[1] = pix & 0xFF; |
|
453 |
+ out[2] = out[3] = pix >> 8; |
|
454 |
+ out += stride; |
|
455 |
+ break; |
|
456 |
+ case 2: |
|
457 |
+ for(i = 0; i < 2; i++) { |
|
458 |
+ uint16_t pix1, pix2; |
|
459 |
+ pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
460 |
+ pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last); |
|
461 |
+ out[0] = pix1 & 0xFF; out[1] = pix1 >> 8; |
|
462 |
+ out[2] = pix2 & 0xFF; out[3] = pix2 >> 8; |
|
463 |
+ out += stride; |
|
464 |
+ out[0] = pix1 & 0xFF; out[1] = pix1 >> 8; |
|
465 |
+ out[2] = pix2 & 0xFF; out[3] = pix2 >> 8; |
|
466 |
+ out += stride; |
|
467 |
+ } |
|
468 |
+ break; |
|
469 |
+ } |
|
470 |
+ blk++; |
|
471 |
+ } |
|
472 |
+ break; |
|
473 |
+ case SMK_BLK_SKIP: |
|
474 |
+ while(run-- && blk < blocks) |
|
475 |
+ blk++; |
|
476 |
+ break; |
|
477 |
+ case SMK_BLK_FILL: |
|
478 |
+ mode = type >> 8; |
|
479 |
+ while(run-- && blk < blocks){ |
|
480 |
+ uint32_t col; |
|
481 |
+ out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4; |
|
482 |
+ col = mode * 0x01010101; |
|
483 |
+ for(i = 0; i < 4; i++) { |
|
484 |
+ *((uint32_t*)out) = col; |
|
485 |
+ out += stride; |
|
486 |
+ } |
|
487 |
+ blk++; |
|
488 |
+ } |
|
489 |
+ break; |
|
490 |
+ } |
|
491 |
+ |
|
492 |
+ } |
|
493 |
+ |
|
494 |
+ *data_size = sizeof(AVFrame); |
|
495 |
+ *(AVFrame*)data = smk->pic; |
|
496 |
+ |
|
497 |
+ /* always report that the buffer was completely consumed */ |
|
498 |
+ return buf_size; |
|
499 |
+} |
|
500 |
+ |
|
501 |
+ |
|
502 |
+ |
|
503 |
+/* |
|
504 |
+ * |
|
505 |
+ * Init smacker decoder |
|
506 |
+ * |
|
507 |
+ */ |
|
508 |
+static int decode_init(AVCodecContext *avctx) |
|
509 |
+{ |
|
510 |
+ SmackVContext * const c = (SmackVContext *)avctx->priv_data; |
|
511 |
+ |
|
512 |
+ c->avctx = avctx; |
|
513 |
+ avctx->has_b_frames = 0; |
|
514 |
+ |
|
515 |
+ c->pic.data[0] = NULL; |
|
516 |
+ |
|
517 |
+ if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) { |
|
518 |
+ return 1; |
|
519 |
+ } |
|
520 |
+ |
|
521 |
+ avctx->pix_fmt = PIX_FMT_PAL8; |
|
522 |
+ |
|
523 |
+ |
|
524 |
+ /* decode huffman trees from extradata */ |
|
525 |
+ if(avctx->extradata_size < 16){ |
|
526 |
+ av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n"); |
|
527 |
+ return -1; |
|
528 |
+ } |
|
529 |
+ |
|
530 |
+ decode_header_trees(c); |
|
531 |
+ |
|
532 |
+ |
|
533 |
+ return 0; |
|
534 |
+} |
|
535 |
+ |
|
536 |
+ |
|
537 |
+ |
|
538 |
+/* |
|
539 |
+ * |
|
540 |
+ * Uninit smacker decoder |
|
541 |
+ * |
|
542 |
+ */ |
|
543 |
+static int decode_end(AVCodecContext *avctx) |
|
544 |
+{ |
|
545 |
+ SmackVContext * const smk = (SmackVContext *)avctx->priv_data; |
|
546 |
+ |
|
547 |
+ if(smk->mmap_tbl) |
|
548 |
+ av_free(smk->mmap_tbl); |
|
549 |
+ if(smk->mclr_tbl) |
|
550 |
+ av_free(smk->mclr_tbl); |
|
551 |
+ if(smk->full_tbl) |
|
552 |
+ av_free(smk->full_tbl); |
|
553 |
+ if(smk->type_tbl) |
|
554 |
+ av_free(smk->type_tbl); |
|
555 |
+ |
|
556 |
+ if (smk->pic.data[0]) |
|
557 |
+ avctx->release_buffer(avctx, &smk->pic); |
|
558 |
+ |
|
559 |
+ return 0; |
|
560 |
+} |
|
561 |
+ |
|
562 |
+ |
|
563 |
+static int smka_decode_init(AVCodecContext *avctx) |
|
564 |
+{ |
|
565 |
+ return 0; |
|
566 |
+} |
|
567 |
+ |
|
568 |
+/** |
|
569 |
+ * Decode Smacker audio data |
|
570 |
+ */ |
|
571 |
+static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) |
|
572 |
+{ |
|
573 |
+ GetBitContext gb; |
|
574 |
+ HuffContext h[4]; |
|
575 |
+ VLC vlc[4]; |
|
576 |
+ int16_t *samples = data; |
|
577 |
+ int val; |
|
578 |
+ int i, res; |
|
579 |
+ int unp_size; |
|
580 |
+ int bits, stereo; |
|
581 |
+ int pred[2] = {0, 0}; |
|
582 |
+ |
|
583 |
+ unp_size = LE_32(buf); |
|
584 |
+ |
|
585 |
+ init_get_bits(&gb, buf + 4, (buf_size - 4) * 8); |
|
586 |
+ |
|
587 |
+ if(!get_bits1(&gb)){ |
|
588 |
+ av_log(avctx, AV_LOG_INFO, "Sound: no data\n"); |
|
589 |
+ *data_size = 0; |
|
590 |
+ return 1; |
|
591 |
+ } |
|
592 |
+ stereo = get_bits1(&gb); |
|
593 |
+ bits = get_bits1(&gb); |
|
594 |
+ |
|
595 |
+ memset(vlc, 0, sizeof(VLC) * 4); |
|
596 |
+ memset(h, 0, sizeof(HuffContext) * 4); |
|
597 |
+ // Initialize |
|
598 |
+ for(i = 0; i < (1 << (bits + stereo)); i++) { |
|
599 |
+ h[i].length = 256; |
|
600 |
+ h[i].maxlength = 0; |
|
601 |
+ h[i].current = 0; |
|
602 |
+ h[i].bits = av_mallocz(256 * 4); |
|
603 |
+ h[i].lengths = av_mallocz(256 * sizeof(int)); |
|
604 |
+ h[i].values = av_mallocz(256 * sizeof(int)); |
|
605 |
+ get_bits1(&gb); |
|
606 |
+ smacker_decode_tree(&gb, &h[i], 0, 0); |
|
607 |
+ get_bits1(&gb); |
|
608 |
+ res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, |
|
609 |
+ h[i].lengths, sizeof(int), sizeof(int), |
|
610 |
+ h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); |
|
611 |
+ if(res < 0) { |
|
612 |
+ av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); |
|
613 |
+ return -1; |
|
614 |
+ } |
|
615 |
+ } |
|
616 |
+ if(bits) { //decode 16-bit data |
|
617 |
+ pred[0] = get_bits(&gb, 8); |
|
618 |
+ pred[0] |= get_bits(&gb, 8); |
|
619 |
+ if(stereo) { |
|
620 |
+ pred[1] = get_bits(&gb, 8); |
|
621 |
+ pred[1] |= get_bits(&gb, 8); |
|
622 |
+ } |
|
623 |
+ for(i = 0; i < unp_size / 2; i++) { |
|
624 |
+ if(i & stereo) { |
|
625 |
+ val = h[2].values[get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3)]; |
|
626 |
+ val |= (int8_t)h[3].values[get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3)] << 8; |
|
627 |
+ pred[1] += val; |
|
628 |
+ *samples++ = pred[1]; |
|
629 |
+ } else { |
|
630 |
+ val = h[0].values[get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3)]; |
|
631 |
+ val |= (int8_t)h[1].values[get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3)] << 8; |
|
632 |
+ pred[0] += val; |
|
633 |
+ *samples++ = pred[0]; |
|
634 |
+ } |
|
635 |
+ } |
|
636 |
+ } else { //8-bit data |
|
637 |
+ pred[0] = get_bits(&gb, 8); |
|
638 |
+ if(stereo) |
|
639 |
+ pred[1] = get_bits(&gb, 8); |
|
640 |
+ for(i = 0; i < unp_size; i++) { |
|
641 |
+ if(i & stereo){ |
|
642 |
+ pred[1] += (int8_t)h[1].values[get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3)]; |
|
643 |
+ *samples++ = (pred[1] - 0x80) << 8; |
|
644 |
+ } else { |
|
645 |
+ pred[0] += (int8_t)h[0].values[get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3)]; |
|
646 |
+ *samples++ = (pred[0] - 0x80) << 8; |
|
647 |
+ } |
|
648 |
+ } |
|
649 |
+ unp_size *= 2; |
|
650 |
+ } |
|
651 |
+ |
|
652 |
+ for(i = 0; i < 4; i++) { |
|
653 |
+ if(vlc[i].table) |
|
654 |
+ free_vlc(&vlc[i]); |
|
655 |
+ if(h[i].bits) |
|
656 |
+ av_free(h[i].bits); |
|
657 |
+ if(h[i].lengths) |
|
658 |
+ av_free(h[i].lengths); |
|
659 |
+ if(h[i].values) |
|
660 |
+ av_free(h[i].values); |
|
661 |
+ } |
|
662 |
+ |
|
663 |
+ *data_size = unp_size; |
|
664 |
+ return buf_size; |
|
665 |
+} |
|
666 |
+ |
|
667 |
+AVCodec smacker_decoder = { |
|
668 |
+ "smackvid", |
|
669 |
+ CODEC_TYPE_VIDEO, |
|
670 |
+ CODEC_ID_SMACKVIDEO, |
|
671 |
+ sizeof(SmackVContext), |
|
672 |
+ decode_init, |
|
673 |
+ NULL, |
|
674 |
+ decode_end, |
|
675 |
+ decode_frame |
|
676 |
+}; |
|
677 |
+ |
|
678 |
+AVCodec smackaud_decoder = { |
|
679 |
+ "smackaud", |
|
680 |
+ CODEC_TYPE_AUDIO, |
|
681 |
+ CODEC_ID_SMACKAUDIO, |
|
682 |
+ 0, |
|
683 |
+ smka_decode_init, |
|
684 |
+ NULL, |
|
685 |
+ NULL, |
|
686 |
+ smka_decode_frame |
|
687 |
+}; |
|
688 |
+ |
... | ... |
@@ -18,7 +18,7 @@ OBJS+=mpeg.o mpegts.o mpegtsenc.o ffm.o crc.o img.o img2.o raw.o rm.o \ |
18 | 18 |
nut.o wc3movie.o mp3.o westwood.o segafilm.o idcin.o flic.o \ |
19 | 19 |
sierravmd.o matroska.o sol.o electronicarts.o nsvdec.o asf.o \ |
20 | 20 |
ogg2.o oggparsevorbis.o oggparsetheora.o oggparseflac.o daud.o aiff.o \ |
21 |
- voc.o tta.o mm.o avs.o |
|
21 |
+ voc.o tta.o mm.o avs.o smacker.o |
|
22 | 22 |
|
23 | 23 |
# muxers |
24 | 24 |
ifeq ($(CONFIG_MUXERS),yes) |
... | ... |
@@ -5,8 +5,8 @@ |
5 | 5 |
extern "C" { |
6 | 6 |
#endif |
7 | 7 |
|
8 |
-#define LIBAVFORMAT_VERSION_INT ((50<<16)+(3<<8)+0) |
|
9 |
-#define LIBAVFORMAT_VERSION 50.3.0 |
|
8 |
+#define LIBAVFORMAT_VERSION_INT ((50<<16)+(4<<8)+0) |
|
9 |
+#define LIBAVFORMAT_VERSION 50.4.0 |
|
10 | 10 |
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT |
11 | 11 |
|
12 | 12 |
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) |
... | ... |
@@ -567,6 +567,9 @@ int mm_init(void); |
567 | 567 |
/* avs.c */ |
568 | 568 |
int avs_init(void); |
569 | 569 |
|
570 |
+/* smacker.c */ |
|
571 |
+int smacker_init(void); |
|
572 |
+ |
|
570 | 573 |
#include "rtp.h" |
571 | 574 |
|
572 | 575 |
#include "rtsp.h" |
573 | 576 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,343 @@ |
0 |
+/* |
|
1 |
+ * Smacker decoder |
|
2 |
+ * Copyright (c) 2006 Konstantin Shishkov. |
|
3 |
+ * |
|
4 |
+ * This library is free software; you can redistribute it and/or |
|
5 |
+ * modify it under the terms of the GNU Lesser General Public |
|
6 |
+ * License as published by the Free Software Foundation; either |
|
7 |
+ * version 2 of the License, or (at your option) any later version. |
|
8 |
+ * |
|
9 |
+ * This library is distributed in the hope that it will be useful, |
|
10 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 |
+ * Lesser General Public License for more details. |
|
13 |
+ * |
|
14 |
+ * You should have received a copy of the GNU Lesser General Public |
|
15 |
+ * License along with this library; if not, write to the Free Software |
|
16 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
17 |
+ */ |
|
18 |
+ |
|
19 |
+/* |
|
20 |
+ * Based on http://wiki.multimedia.cx/index.php?title=Smacker |
|
21 |
+ */ |
|
22 |
+ |
|
23 |
+#include "avformat.h" |
|
24 |
+#include "avi.h" |
|
25 |
+#include "bswap.h" |
|
26 |
+ |
|
27 |
+#define SMACKER_PAL 0x01 |
|
28 |
+ |
|
29 |
+enum SAudFlags { |
|
30 |
+ SMK_AUD_PACKED = 0x80000000, |
|
31 |
+ SMK_AUD_16BITS = 0x20000000, |
|
32 |
+ SMK_AUD_STEREO = 0x10000000, |
|
33 |
+ SMK_AUD_BINKAUD = 0x08000000, |
|
34 |
+ SMK_AUD_USEDCT = 0x04000000 |
|
35 |
+}; |
|
36 |
+ |
|
37 |
+typedef struct SmackerContext { |
|
38 |
+ /* Smacker file header */ |
|
39 |
+ uint32_t magic; |
|
40 |
+ uint32_t width, height; |
|
41 |
+ uint32_t frames; |
|
42 |
+ int pts_inc; |
|
43 |
+ uint32_t flags; |
|
44 |
+ uint32_t audio[7]; |
|
45 |
+ uint32_t treesize; |
|
46 |
+ uint32_t mmap_size, mclr_size, full_size, type_size; |
|
47 |
+ uint32_t rates[7]; |
|
48 |
+ uint32_t pad; |
|
49 |
+ /* frame info */ |
|
50 |
+ uint32_t *frm_size; |
|
51 |
+ uint8_t *frm_flags; |
|
52 |
+ /* internal variables */ |
|
53 |
+ int cur_frame; |
|
54 |
+ int is_ver4; |
|
55 |
+ int64_t cur_pts; |
|
56 |
+ /* current frame for demuxing */ |
|
57 |
+ uint8_t pal[768]; |
|
58 |
+ int indexes[7]; |
|
59 |
+ int videoindex; |
|
60 |
+ uint8_t *bufs[7]; |
|
61 |
+ int buf_sizes[7]; |
|
62 |
+ int stream_id[7]; |
|
63 |
+ int curstream; |
|
64 |
+ offset_t nextpos; |
|
65 |
+} SmackerContext; |
|
66 |
+ |
|
67 |
+typedef struct SmackerFrame { |
|
68 |
+ int64_t pts; |
|
69 |
+ int stream; |
|
70 |
+} SmackerFrame; |
|
71 |
+ |
|
72 |
+/* palette used in Smacker */ |
|
73 |
+static const uint8_t smk_pal[64] = { |
|
74 |
+ 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C, |
|
75 |
+ 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C, |
|
76 |
+ 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D, |
|
77 |
+ 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D, |
|
78 |
+ 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E, |
|
79 |
+ 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE, |
|
80 |
+ 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF, |
|
81 |
+ 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF |
|
82 |
+}; |
|
83 |
+ |
|
84 |
+ |
|
85 |
+static int smacker_probe(AVProbeData *p) |
|
86 |
+{ |
|
87 |
+ if (p->buf_size < 4) |
|
88 |
+ return 0; |
|
89 |
+ if(p->buf[0] == 'S' && p->buf[1] == 'M' && p->buf[2] == 'K' |
|
90 |
+ && (p->buf[3] == '2' || p->buf[3] == '4')) |
|
91 |
+ return AVPROBE_SCORE_MAX; |
|
92 |
+ else |
|
93 |
+ return 0; |
|
94 |
+} |
|
95 |
+ |
|
96 |
+static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap) |
|
97 |
+{ |
|
98 |
+ ByteIOContext *pb = &s->pb; |
|
99 |
+ SmackerContext *smk = (SmackerContext *)s->priv_data; |
|
100 |
+ AVStream *st, *ast[7]; |
|
101 |
+ int i, ret; |
|
102 |
+ int tbase; |
|
103 |
+ |
|
104 |
+ /* read and check header */ |
|
105 |
+ smk->magic = get_le32(pb); |
|
106 |
+ if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4')) |
|
107 |
+ return -1; |
|
108 |
+ smk->width = get_le32(pb); |
|
109 |
+ smk->height = get_le32(pb); |
|
110 |
+ smk->frames = get_le32(pb); |
|
111 |
+ smk->pts_inc = (int32_t)get_le32(pb); |
|
112 |
+ smk->flags = get_le32(pb); |
|
113 |
+ for(i = 0; i < 7; i++) |
|
114 |
+ smk->audio[i] = get_le32(pb); |
|
115 |
+ smk->treesize = get_le32(pb); |
|
116 |
+ smk->mmap_size = get_le32(pb); |
|
117 |
+ smk->mclr_size = get_le32(pb); |
|
118 |
+ smk->full_size = get_le32(pb); |
|
119 |
+ smk->type_size = get_le32(pb); |
|
120 |
+ for(i = 0; i < 7; i++) |
|
121 |
+ smk->rates[i] = get_le32(pb); |
|
122 |
+ smk->pad = get_le32(pb); |
|
123 |
+ /* setup data */ |
|
124 |
+ if(smk->frames > 0xFFFFFF) { |
|
125 |
+ av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames); |
|
126 |
+ return -1; |
|
127 |
+ } |
|
128 |
+ smk->frm_size = av_malloc(smk->frames * 4); |
|
129 |
+ smk->frm_flags = av_malloc(smk->frames); |
|
130 |
+ |
|
131 |
+ smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2')); |
|
132 |
+ |
|
133 |
+ /* read frame info */ |
|
134 |
+ for(i = 0; i < smk->frames; i++) { |
|
135 |
+ smk->frm_size[i] = get_le32(pb); |
|
136 |
+ } |
|
137 |
+ for(i = 0; i < smk->frames; i++) { |
|
138 |
+ smk->frm_flags[i] = get_byte(pb); |
|
139 |
+ } |
|
140 |
+ |
|
141 |
+ /* init video codec */ |
|
142 |
+ st = av_new_stream(s, 0); |
|
143 |
+ if (!st) |
|
144 |
+ return -1; |
|
145 |
+ smk->videoindex = st->index; |
|
146 |
+ st->codec->width = smk->width; |
|
147 |
+ st->codec->height = smk->height; |
|
148 |
+ st->codec->pix_fmt = PIX_FMT_PAL8; |
|
149 |
+ st->codec->codec_type = CODEC_TYPE_VIDEO; |
|
150 |
+ st->codec->codec_id = CODEC_ID_SMACKVIDEO; |
|
151 |
+ st->codec->codec_tag = smk->is_ver4; |
|
152 |
+ /* Smacker uses 100000 as internal timebase */ |
|
153 |
+ if(smk->pts_inc < 0) |
|
154 |
+ smk->pts_inc = -smk->pts_inc; |
|
155 |
+ else |
|
156 |
+ smk->pts_inc *= 100; |
|
157 |
+ tbase = 100000; |
|
158 |
+ av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1); |
|
159 |
+ av_set_pts_info(st, 33, smk->pts_inc, tbase); |
|
160 |
+ /* handle possible audio streams */ |
|
161 |
+ for(i = 0; i < 7; i++) { |
|
162 |
+ smk->indexes[i] = -1; |
|
163 |
+ if((smk->rates[i] & 0xFFFFFF) && !(smk->rates[i] & SMK_AUD_BINKAUD)){ |
|
164 |
+ ast[i] = av_new_stream(s, 0); |
|
165 |
+ smk->indexes[i] = ast[i]->index; |
|
166 |
+ av_set_pts_info(ast[i], 33, smk->pts_inc, tbase); |
|
167 |
+ ast[i]->codec->codec_type = CODEC_TYPE_AUDIO; |
|
168 |
+ ast[i]->codec->codec_id = (smk->rates[i] & SMK_AUD_PACKED) ? CODEC_ID_SMACKAUDIO : CODEC_ID_PCM_U8; |
|
169 |
+ ast[i]->codec->codec_tag = 0; |
|
170 |
+ ast[i]->codec->channels = (smk->rates[i] & SMK_AUD_STEREO) ? 2 : 1; |
|
171 |
+ ast[i]->codec->sample_rate = smk->rates[i] & 0xFFFFFF; |
|
172 |
+ ast[i]->codec->bits_per_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8; |
|
173 |
+ if(ast[i]->codec->bits_per_sample == 16 && ast[i]->codec->codec_id == CODEC_ID_PCM_U8) |
|
174 |
+ ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE; |
|
175 |
+ } |
|
176 |
+ } |
|
177 |
+ |
|
178 |
+ |
|
179 |
+ /* load trees to extradata, they will be unpacked by decoder */ |
|
180 |
+ st->codec->extradata = av_malloc(smk->treesize + 16); |
|
181 |
+ st->codec->extradata_size = smk->treesize + 16; |
|
182 |
+ if(!st->codec->extradata){ |
|
183 |
+ av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16); |
|
184 |
+ av_free(smk->frm_size); |
|
185 |
+ av_free(smk->frm_flags); |
|
186 |
+ return -1; |
|
187 |
+ } |
|
188 |
+ ret = get_buffer(pb, st->codec->extradata + 16, st->codec->extradata_size - 16); |
|
189 |
+ if(ret != st->codec->extradata_size - 16){ |
|
190 |
+ av_free(smk->frm_size); |
|
191 |
+ av_free(smk->frm_flags); |
|
192 |
+ return AVERROR_IO; |
|
193 |
+ } |
|
194 |
+ ((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size); |
|
195 |
+ ((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size); |
|
196 |
+ ((int32_t*)st->codec->extradata)[2] = le2me_32(smk->full_size); |
|
197 |
+ ((int32_t*)st->codec->extradata)[3] = le2me_32(smk->type_size); |
|
198 |
+ |
|
199 |
+ smk->curstream = -1; |
|
200 |
+ smk->nextpos = url_ftell(pb); |
|
201 |
+ |
|
202 |
+ return 0; |
|
203 |
+} |
|
204 |
+ |
|
205 |
+ |
|
206 |
+static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
207 |
+{ |
|
208 |
+ SmackerContext *smk = (SmackerContext *)s->priv_data; |
|
209 |
+ int flags; |
|
210 |
+ int ret; |
|
211 |
+ int i; |
|
212 |
+ int frame_size = 0; |
|
213 |
+ int palchange = 0; |
|
214 |
+ int pos; |
|
215 |
+ |
|
216 |
+ if (url_feof(&s->pb) || smk->cur_frame >= smk->frames) |
|
217 |
+ return -EIO; |
|
218 |
+ |
|
219 |
+ /* if we demuxed all streams, pass another frame */ |
|
220 |
+ if(smk->curstream < 0) { |
|
221 |
+ url_fseek(&s->pb, smk->nextpos, 0); |
|
222 |
+ frame_size = smk->frm_size[smk->cur_frame] & (~3); |
|
223 |
+ flags = smk->frm_flags[smk->cur_frame]; |
|
224 |
+ /* handle palette change event */ |
|
225 |
+ pos = url_ftell(&s->pb); |
|
226 |
+ if(flags & SMACKER_PAL){ |
|
227 |
+ int size, sz, t, off, j, pos; |
|
228 |
+ uint8_t *pal = smk->pal; |
|
229 |
+ uint8_t oldpal[768]; |
|
230 |
+ |
|
231 |
+ memcpy(oldpal, pal, 768); |
|
232 |
+ size = get_byte(&s->pb); |
|
233 |
+ size = size * 4 - 1; |
|
234 |
+ frame_size -= size; |
|
235 |
+ frame_size--; |
|
236 |
+ sz = 0; |
|
237 |
+ pos = url_ftell(&s->pb) + size; |
|
238 |
+ while(sz < 256){ |
|
239 |
+ t = get_byte(&s->pb); |
|
240 |
+ if(t & 0x80){ /* skip palette entries */ |
|
241 |
+ sz += (t & 0x7F) + 1; |
|
242 |
+ pal += ((t & 0x7F) + 1) * 3; |
|
243 |
+ } else if(t & 0x40){ /* copy with offset */ |
|
244 |
+ off = get_byte(&s->pb) * 3; |
|
245 |
+ j = (t & 0x3F) + 1; |
|
246 |
+ while(j-- && sz < 256) { |
|
247 |
+ *pal++ = oldpal[off + 0]; |
|
248 |
+ *pal++ = oldpal[off + 1]; |
|
249 |
+ *pal++ = oldpal[off + 2]; |
|
250 |
+ sz++; |
|
251 |
+ off += 3; |
|
252 |
+ } |
|
253 |
+ } else { /* new entries */ |
|
254 |
+ *pal++ = smk_pal[t]; |
|
255 |
+ *pal++ = smk_pal[get_byte(&s->pb) & 0x3F]; |
|
256 |
+ *pal++ = smk_pal[get_byte(&s->pb) & 0x3F]; |
|
257 |
+ sz++; |
|
258 |
+ } |
|
259 |
+ } |
|
260 |
+ url_fseek(&s->pb, pos, 0); |
|
261 |
+ palchange |= 1; |
|
262 |
+ } |
|
263 |
+ flags >>= 1; |
|
264 |
+ smk->curstream = -1; |
|
265 |
+ /* if audio chunks are present, put them to stack and retrieve later */ |
|
266 |
+ for(i = 0; i < 7; i++) { |
|
267 |
+ if(flags & 1) { |
|
268 |
+ int size; |
|
269 |
+ size = get_le32(&s->pb) - 4; |
|
270 |
+ frame_size -= size; |
|
271 |
+ frame_size -= 4; |
|
272 |
+ smk->curstream++; |
|
273 |
+ smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size); |
|
274 |
+ smk->buf_sizes[smk->curstream] = size; |
|
275 |
+ ret = get_buffer(&s->pb, smk->bufs[smk->curstream], size); |
|
276 |
+ if(ret != size) |
|
277 |
+ return AVERROR_IO; |
|
278 |
+ smk->stream_id[smk->curstream] = smk->indexes[i]; |
|
279 |
+ } |
|
280 |
+ flags >>= 1; |
|
281 |
+ } |
|
282 |
+ if (av_new_packet(pkt, frame_size + 768)) |
|
283 |
+ return AVERROR_NOMEM; |
|
284 |
+ if(smk->frm_size[smk->cur_frame] & 1) |
|
285 |
+ palchange |= 2; |
|
286 |
+ pkt->data[0] = palchange; |
|
287 |
+ memcpy(pkt->data + 1, smk->pal, 768); |
|
288 |
+ ret = get_buffer(&s->pb, pkt->data + 769, frame_size); |
|
289 |
+ if(ret != frame_size) |
|
290 |
+ return AVERROR_IO; |
|
291 |
+ pkt->stream_index = smk->videoindex; |
|
292 |
+ pkt->size = ret + 769; |
|
293 |
+ smk->cur_frame++; |
|
294 |
+ smk->nextpos = url_ftell(&s->pb); |
|
295 |
+ } else { |
|
296 |
+ if (av_new_packet(pkt, smk->buf_sizes[smk->curstream])) |
|
297 |
+ return AVERROR_NOMEM; |
|
298 |
+ memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]); |
|
299 |
+ pkt->size = smk->buf_sizes[smk->curstream]; |
|
300 |
+ pkt->stream_index = smk->stream_id[smk->curstream]; |
|
301 |
+ smk->curstream--; |
|
302 |
+ } |
|
303 |
+ |
|
304 |
+ return 0; |
|
305 |
+} |
|
306 |
+ |
|
307 |
+static int smacker_read_close(AVFormatContext *s) |
|
308 |
+{ |
|
309 |
+ SmackerContext *smk = (SmackerContext *)s->priv_data; |
|
310 |
+ int i; |
|
311 |
+ |
|
312 |
+ for(i = 0; i < 7; i++) |
|
313 |
+ if(smk->bufs[i]) |
|
314 |
+ av_free(smk->bufs[i]); |
|
315 |
+ if(smk->frm_size) |
|
316 |
+ av_free(smk->frm_size); |
|
317 |
+ if(smk->frm_flags) |
|
318 |
+ av_free(smk->frm_flags); |
|
319 |
+ |
|
320 |
+ for(i=0;i<s->nb_streams;i++) { |
|
321 |
+ AVStream *st = s->streams[i]; |
|
322 |
+ if(st->codec->extradata) |
|
323 |
+ av_free(st->codec->extradata); |
|
324 |
+ } |
|
325 |
+ return 0; |
|
326 |
+} |
|
327 |
+ |
|
328 |
+static AVInputFormat smacker_iformat = { |
|
329 |
+ "smk", |
|
330 |
+ "Smacker Video", |
|
331 |
+ sizeof(SmackerContext), |
|
332 |
+ smacker_probe, |
|
333 |
+ smacker_read_header, |
|
334 |
+ smacker_read_packet, |
|
335 |
+ smacker_read_close, |
|
336 |
+}; |
|
337 |
+ |
|
338 |
+int smacker_init(void) |
|
339 |
+{ |
|
340 |
+ av_register_input_format(&smacker_iformat); |
|
341 |
+ return 0; |
|
342 |
+} |