annotate smacker.c @ 5910:536e5527c1e0 libavformat

Define AVMediaType enum, and use it instead of enum CodecType, which is deprecated and will be dropped at the next major bump.
author stefano
date Tue, 30 Mar 2010 23:30:55 +0000
parents cdc913460d61
children 224077f3c564
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
1 /*
1415
3b00fb8ef8e4 replace coder/decoder file description in libavformat by muxer/demuxer
aurel
parents: 1358
diff changeset
2 * Smacker demuxer
4251
77e0c7511d41 cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents: 4201
diff changeset
3 * Copyright (c) 2006 Konstantin Shishkov
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
4 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
5 * This file is part of FFmpeg.
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
6 *
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
11 *
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
15 * Lesser General Public License for more details.
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
16 *
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
1358
0899bfe4105c Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents: 1172
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
20 */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
21
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
22 /*
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
23 * Based on http://wiki.multimedia.cx/index.php?title=Smacker
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
24 */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
25
3286
6f61c3b36632 Use full path for #includes from another directory.
diego
parents: 2771
diff changeset
26 #include "libavutil/bswap.h"
4201
7d2f3f1b68d8 Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents: 3973
diff changeset
27 #include "libavutil/intreadwrite.h"
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
28 #include "avformat.h"
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
29
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
30 #define SMACKER_PAL 0x01
2404
2ca025105808 Take ring frame into account when demuxing.
kostya
parents: 2274
diff changeset
31 #define SMACKER_FLAG_RING_FRAME 0x01
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
32
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
33 enum SAudFlags {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
34 SMK_AUD_PACKED = 0x80000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
35 SMK_AUD_16BITS = 0x20000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
36 SMK_AUD_STEREO = 0x10000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
37 SMK_AUD_BINKAUD = 0x08000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
38 SMK_AUD_USEDCT = 0x04000000
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
39 };
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
40
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
41 typedef struct SmackerContext {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
42 /* Smacker file header */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
43 uint32_t magic;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
44 uint32_t width, height;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
45 uint32_t frames;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
46 int pts_inc;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
47 uint32_t flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
48 uint32_t audio[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
49 uint32_t treesize;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
50 uint32_t mmap_size, mclr_size, full_size, type_size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
51 uint32_t rates[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
52 uint32_t pad;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
53 /* frame info */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
54 uint32_t *frm_size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
55 uint8_t *frm_flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
56 /* internal variables */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
57 int cur_frame;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
58 int is_ver4;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
59 int64_t cur_pts;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
60 /* current frame for demuxing */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
61 uint8_t pal[768];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
62 int indexes[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
63 int videoindex;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
64 uint8_t *bufs[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
65 int buf_sizes[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
66 int stream_id[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
67 int curstream;
3973
549a09cf23fe Remove offset_t typedef and use int64_t directly instead.
diego
parents: 3908
diff changeset
68 int64_t nextpos;
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
69 int64_t aud_pts[7];
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
70 } SmackerContext;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
71
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
72 typedef struct SmackerFrame {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
73 int64_t pts;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
74 int stream;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
75 } SmackerFrame;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
76
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
77 /* palette used in Smacker */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
78 static const uint8_t smk_pal[64] = {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
79 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
80 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
81 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
82 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
83 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
84 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
85 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
86 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
87 };
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
88
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
89
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
90 static int smacker_probe(AVProbeData *p)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
91 {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
92 if(p->buf[0] == 'S' && p->buf[1] == 'M' && p->buf[2] == 'K'
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
93 && (p->buf[3] == '2' || p->buf[3] == '4'))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
94 return AVPROBE_SCORE_MAX;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
95 else
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
96 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
97 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
98
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
99 static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
100 {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
101 ByteIOContext *pb = s->pb;
2006
2f0154760e5f Get rid of unnecessary pointer casts.
diego
parents: 2001
diff changeset
102 SmackerContext *smk = s->priv_data;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
103 AVStream *st, *ast[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
104 int i, ret;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
105 int tbase;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
106
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
107 /* read and check header */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
108 smk->magic = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
109 if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4'))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
110 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
111 smk->width = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
112 smk->height = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
113 smk->frames = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
114 smk->pts_inc = (int32_t)get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
115 smk->flags = get_le32(pb);
2404
2ca025105808 Take ring frame into account when demuxing.
kostya
parents: 2274
diff changeset
116 if(smk->flags & SMACKER_FLAG_RING_FRAME)
2ca025105808 Take ring frame into account when demuxing.
kostya
parents: 2274
diff changeset
117 smk->frames++;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
118 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
119 smk->audio[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
120 smk->treesize = get_le32(pb);
1079
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
121
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
122 if(smk->treesize >= UINT_MAX/4){ // smk->treesize + 16 must not overflow (this check is probably redundant)
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
123 av_log(s, AV_LOG_ERROR, "treesize too large\n");
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
124 return -1;
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
125 }
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
126
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
127 //FIXME remove extradata "rebuilding"
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
128 smk->mmap_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
129 smk->mclr_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
130 smk->full_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
131 smk->type_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
132 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
133 smk->rates[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
134 smk->pad = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
135 /* setup data */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
136 if(smk->frames > 0xFFFFFF) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
137 av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
138 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
139 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
140 smk->frm_size = av_malloc(smk->frames * 4);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
141 smk->frm_flags = av_malloc(smk->frames);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
142
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
143 smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2'));
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
144
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
145 /* read frame info */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
146 for(i = 0; i < smk->frames; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
147 smk->frm_size[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
148 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
149 for(i = 0; i < smk->frames; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
150 smk->frm_flags[i] = get_byte(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
151 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
152
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
153 /* init video codec */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
154 st = av_new_stream(s, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
155 if (!st)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
156 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
157 smk->videoindex = st->index;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
158 st->codec->width = smk->width;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
159 st->codec->height = smk->height;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
160 st->codec->pix_fmt = PIX_FMT_PAL8;
5910
536e5527c1e0 Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 5608
diff changeset
161 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
162 st->codec->codec_id = CODEC_ID_SMACKVIDEO;
1089
0319672689ef Now MPlayer should understand Smacker audio and video codecs.
kostya
parents: 1079
diff changeset
163 st->codec->codec_tag = smk->magic;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
164 /* Smacker uses 100000 as internal timebase */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
165 if(smk->pts_inc < 0)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
166 smk->pts_inc = -smk->pts_inc;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
167 else
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
168 smk->pts_inc *= 100;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
169 tbase = 100000;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
170 av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
171 av_set_pts_info(st, 33, smk->pts_inc, tbase);
5608
cdc913460d61 Set duration in Smacker demuxer
daniel
parents: 5607
diff changeset
172 st->duration = smk->frames;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
173 /* handle possible audio streams */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
174 for(i = 0; i < 7; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
175 smk->indexes[i] = -1;
5607
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
176 if(smk->rates[i] & 0xFFFFFF){
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
177 ast[i] = av_new_stream(s, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
178 smk->indexes[i] = ast[i]->index;
5910
536e5527c1e0 Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents: 5608
diff changeset
179 ast[i]->codec->codec_type = AVMEDIA_TYPE_AUDIO;
5607
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
180 if (smk->rates[i] & SMK_AUD_BINKAUD) {
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
181 ast[i]->codec->codec_id = CODEC_ID_BINKAUDIO_RDFT;
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
182 } else if (smk->rates[i] & SMK_AUD_USEDCT) {
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
183 ast[i]->codec->codec_id = CODEC_ID_BINKAUDIO_DCT;
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
184 } else if (smk->rates[i] & SMK_AUD_PACKED){
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
185 ast[i]->codec->codec_id = CODEC_ID_SMACKAUDIO;
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
186 ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A');
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
187 } else {
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
188 ast[i]->codec->codec_id = CODEC_ID_PCM_U8;
9143e8efec99 Demux Bink audio in Smacker files
daniel
parents: 5339
diff changeset
189 }
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
190 ast[i]->codec->channels = (smk->rates[i] & SMK_AUD_STEREO) ? 2 : 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
191 ast[i]->codec->sample_rate = smk->rates[i] & 0xFFFFFF;
3908
1d3d17de20ba Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 3424
diff changeset
192 ast[i]->codec->bits_per_coded_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8;
1d3d17de20ba Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 3424
diff changeset
193 if(ast[i]->codec->bits_per_coded_sample == 16 && ast[i]->codec->codec_id == CODEC_ID_PCM_U8)
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
194 ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
195 av_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate
3908
1d3d17de20ba Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents: 3424
diff changeset
196 * ast[i]->codec->channels * ast[i]->codec->bits_per_coded_sample / 8);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
197 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
198 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
199
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
200
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
201 /* load trees to extradata, they will be unpacked by decoder */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
202 st->codec->extradata = av_malloc(smk->treesize + 16);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
203 st->codec->extradata_size = smk->treesize + 16;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
204 if(!st->codec->extradata){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
205 av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
206 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
207 av_free(smk->frm_flags);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
208 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
209 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
210 ret = get_buffer(pb, st->codec->extradata + 16, st->codec->extradata_size - 16);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
211 if(ret != st->codec->extradata_size - 16){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
212 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
213 av_free(smk->frm_flags);
2274
b21c2af60bc9 Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents: 2273
diff changeset
214 return AVERROR(EIO);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
215 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
216 ((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
217 ((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
218 ((int32_t*)st->codec->extradata)[2] = le2me_32(smk->full_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
219 ((int32_t*)st->codec->extradata)[3] = le2me_32(smk->type_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
220
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
221 smk->curstream = -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
222 smk->nextpos = url_ftell(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
223
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
224 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
225 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
226
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
227
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
228 static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
229 {
2006
2f0154760e5f Get rid of unnecessary pointer casts.
diego
parents: 2001
diff changeset
230 SmackerContext *smk = s->priv_data;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
231 int flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
232 int ret;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
233 int i;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
234 int frame_size = 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
235 int palchange = 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
236 int pos;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
237
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
238 if (url_feof(s->pb) || smk->cur_frame >= smk->frames)
1787
eb16c64144ee This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents: 1673
diff changeset
239 return AVERROR(EIO);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
240
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
241 /* if we demuxed all streams, pass another frame */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
242 if(smk->curstream < 0) {
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
243 url_fseek(s->pb, smk->nextpos, 0);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
244 frame_size = smk->frm_size[smk->cur_frame] & (~3);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
245 flags = smk->frm_flags[smk->cur_frame];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
246 /* handle palette change event */
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
247 pos = url_ftell(s->pb);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
248 if(flags & SMACKER_PAL){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
249 int size, sz, t, off, j, pos;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
250 uint8_t *pal = smk->pal;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
251 uint8_t oldpal[768];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
252
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
253 memcpy(oldpal, pal, 768);
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
254 size = get_byte(s->pb);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
255 size = size * 4 - 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
256 frame_size -= size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
257 frame_size--;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
258 sz = 0;
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
259 pos = url_ftell(s->pb) + size;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
260 while(sz < 256){
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
261 t = get_byte(s->pb);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
262 if(t & 0x80){ /* skip palette entries */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
263 sz += (t & 0x7F) + 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
264 pal += ((t & 0x7F) + 1) * 3;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
265 } else if(t & 0x40){ /* copy with offset */
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
266 off = get_byte(s->pb) * 3;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
267 j = (t & 0x3F) + 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
268 while(j-- && sz < 256) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
269 *pal++ = oldpal[off + 0];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
270 *pal++ = oldpal[off + 1];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
271 *pal++ = oldpal[off + 2];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
272 sz++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
273 off += 3;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
274 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
275 } else { /* new entries */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
276 *pal++ = smk_pal[t];
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
277 *pal++ = smk_pal[get_byte(s->pb) & 0x3F];
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
278 *pal++ = smk_pal[get_byte(s->pb) & 0x3F];
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
279 sz++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
280 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
281 }
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
282 url_fseek(s->pb, pos, 0);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
283 palchange |= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
284 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
285 flags >>= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
286 smk->curstream = -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
287 /* if audio chunks are present, put them to stack and retrieve later */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
288 for(i = 0; i < 7; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
289 if(flags & 1) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
290 int size;
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
291 size = get_le32(s->pb) - 4;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
292 frame_size -= size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
293 frame_size -= 4;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
294 smk->curstream++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
295 smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
296 smk->buf_sizes[smk->curstream] = size;
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
297 ret = get_buffer(s->pb, smk->bufs[smk->curstream], size);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
298 if(ret != size)
2274
b21c2af60bc9 Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents: 2273
diff changeset
299 return AVERROR(EIO);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
300 smk->stream_id[smk->curstream] = smk->indexes[i];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
301 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
302 flags >>= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
303 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
304 if (av_new_packet(pkt, frame_size + 768))
2273
7eb456c4ed8a Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents: 2006
diff changeset
305 return AVERROR(ENOMEM);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
306 if(smk->frm_size[smk->cur_frame] & 1)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
307 palchange |= 2;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
308 pkt->data[0] = palchange;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
309 memcpy(pkt->data + 1, smk->pal, 768);
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
310 ret = get_buffer(s->pb, pkt->data + 769, frame_size);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
311 if(ret != frame_size)
2274
b21c2af60bc9 Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents: 2273
diff changeset
312 return AVERROR(EIO);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
313 pkt->stream_index = smk->videoindex;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
314 pkt->size = ret + 769;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
315 smk->cur_frame++;
2771
d52c718e83f9 Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents: 2404
diff changeset
316 smk->nextpos = url_ftell(s->pb);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
317 } else {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
318 if (av_new_packet(pkt, smk->buf_sizes[smk->curstream]))
2273
7eb456c4ed8a Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents: 2006
diff changeset
319 return AVERROR(ENOMEM);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
320 memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
321 pkt->size = smk->buf_sizes[smk->curstream];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
322 pkt->stream_index = smk->stream_id[smk->curstream];
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
323 pkt->pts = smk->aud_pts[smk->curstream];
1673
a782462e2497 rename BE/LE_8/16/32 to AV_RL/B_8/16/32
alex
parents: 1415
diff changeset
324 smk->aud_pts[smk->curstream] += AV_RL32(pkt->data);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
325 smk->curstream--;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
326 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
327
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
328 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
329 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
330
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
331 static int smacker_read_close(AVFormatContext *s)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
332 {
2006
2f0154760e5f Get rid of unnecessary pointer casts.
diego
parents: 2001
diff changeset
333 SmackerContext *smk = s->priv_data;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
334 int i;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
335
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
336 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
337 if(smk->bufs[i])
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
338 av_free(smk->bufs[i]);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
339 if(smk->frm_size)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
340 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
341 if(smk->frm_flags)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
342 av_free(smk->frm_flags);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
343
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
344 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
345 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
346
1169
d18cc9a1fd02 allow individual selection of muxers and demuxers
mru
parents: 1167
diff changeset
347 AVInputFormat smacker_demuxer = {
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
348 "smk",
3424
7a0230981402 Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents: 3399
diff changeset
349 NULL_IF_CONFIG_SMALL("Smacker video"),
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
350 sizeof(SmackerContext),
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
351 smacker_probe,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
352 smacker_read_header,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
353 smacker_read_packet,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
354 smacker_read_close,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
355 };