Browse code

Smacker demuxer and decoder.

Originally committed as revision 5189 to svn://svn.ffmpeg.org/ffmpeg/trunk

Kostya Shishkov authored on 2006/03/22 02:27:47
Showing 10 changed files
... ...
@@ -41,6 +41,7 @@ version <next>
41 41
 - Improved Theora/VP3 decoder
42 42
 - True Audio (TTA) decoder
43 43
 - AVS demuxer and video decoder
44
+- Smacker demuxer and decoder
44 45
 
45 46
 version 0.4.9-pre1:
46 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.
... ...
@@ -146,6 +146,9 @@ endif
146 146
 ifeq ($(CONFIG_SHORTEN_DECODER),yes)
147 147
     OBJS+= shorten.o
148 148
 endif
149
+ifneq ($(CONFIG_SMACKER_DECODER)$(CONFIG_SMACKAUD_DECODER),)
150
+    OBJS+= smacker.o
151
+endif
149 152
 ifeq ($(CONFIG_SMC_DECODER),yes)
150 153
     OBJS+= smc.o
151 154
 endif
... ...
@@ -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)
... ...
@@ -80,6 +80,7 @@ void av_register_all(void)
80 80
     flic_init();
81 81
     vmd_init();
82 82
     mm_init();
83
+    smacker_init();
83 84
 
84 85
 #if defined(AMR_NB) || defined(AMR_NB_FIXED) || defined(AMR_WB)
85 86
     amr_init();
... ...
@@ -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
+}