annotate smacker.c @ 1942:70b741fa63eb libavformat

The NSV demuxer assumes that a video frame's timestamp increases by one on each frame, but some low-bitrate NSV files omit video frames for some NSV frames, and expect the timestamp to increase by one every NSV frame. This is noticeable in 64vp3.nsv where the video runs several times faster than the audio. Fix this by unconditionally incrementing the video's timestamp with each NSV frame. patch by David Conrad, umovimus gmail com
author diego
date Wed, 21 Mar 2007 11:05:35 +0000
parents eb16c64144ee
children 1a3c9056982a
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
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
3 * Copyright (c) 2006 Konstantin Shishkov.
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
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
26 #include "avformat.h"
1172
6a5e58d2114b move common stuff from avienc.c and wav.c to new file riff.c
mru
parents: 1169
diff changeset
27 #include "riff.h"
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
28 #include "bswap.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
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
31
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
32 enum SAudFlags {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
33 SMK_AUD_PACKED = 0x80000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
34 SMK_AUD_16BITS = 0x20000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
35 SMK_AUD_STEREO = 0x10000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
36 SMK_AUD_BINKAUD = 0x08000000,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
37 SMK_AUD_USEDCT = 0x04000000
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
38 };
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
39
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
40 typedef struct SmackerContext {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
41 /* Smacker file header */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
42 uint32_t magic;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
43 uint32_t width, height;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
44 uint32_t frames;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
45 int pts_inc;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
46 uint32_t flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
47 uint32_t audio[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
48 uint32_t treesize;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
49 uint32_t mmap_size, mclr_size, full_size, type_size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
50 uint32_t rates[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
51 uint32_t pad;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
52 /* frame info */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
53 uint32_t *frm_size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
54 uint8_t *frm_flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
55 /* internal variables */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
56 int cur_frame;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
57 int is_ver4;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
58 int64_t cur_pts;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
59 /* current frame for demuxing */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
60 uint8_t pal[768];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
61 int indexes[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
62 int videoindex;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
63 uint8_t *bufs[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
64 int buf_sizes[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
65 int stream_id[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
66 int curstream;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
67 offset_t nextpos;
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
68 int64_t aud_pts[7];
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
69 } SmackerContext;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
70
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
71 typedef struct SmackerFrame {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
72 int64_t pts;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
73 int stream;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
74 } SmackerFrame;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
75
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
76 /* palette used in Smacker */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
77 static const uint8_t smk_pal[64] = {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
78 0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x18, 0x1C,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
79 0x20, 0x24, 0x28, 0x2C, 0x30, 0x34, 0x38, 0x3C,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
80 0x41, 0x45, 0x49, 0x4D, 0x51, 0x55, 0x59, 0x5D,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
81 0x61, 0x65, 0x69, 0x6D, 0x71, 0x75, 0x79, 0x7D,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
82 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9A, 0x9E,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
83 0xA2, 0xA6, 0xAA, 0xAE, 0xB2, 0xB6, 0xBA, 0xBE,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
84 0xC3, 0xC7, 0xCB, 0xCF, 0xD3, 0xD7, 0xDB, 0xDF,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
85 0xE3, 0xE7, 0xEB, 0xEF, 0xF3, 0xF7, 0xFB, 0xFF
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
86 };
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 static int smacker_probe(AVProbeData *p)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
90 {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
91 if (p->buf_size < 4)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
92 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
93 if(p->buf[0] == 'S' && p->buf[1] == 'M' && p->buf[2] == 'K'
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
94 && (p->buf[3] == '2' || p->buf[3] == '4'))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
95 return AVPROBE_SCORE_MAX;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
96 else
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
97 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
98 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
99
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
100 static int smacker_read_header(AVFormatContext *s, AVFormatParameters *ap)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
101 {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
102 ByteIOContext *pb = &s->pb;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
103 SmackerContext *smk = (SmackerContext *)s->priv_data;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
104 AVStream *st, *ast[7];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
105 int i, ret;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
106 int tbase;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
107
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
108 /* read and check header */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
109 smk->magic = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
110 if (smk->magic != MKTAG('S', 'M', 'K', '2') && smk->magic != MKTAG('S', 'M', 'K', '4'))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
111 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
112 smk->width = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
113 smk->height = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
114 smk->frames = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
115 smk->pts_inc = (int32_t)get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
116 smk->flags = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
117 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
118 smk->audio[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
119 smk->treesize = get_le32(pb);
1079
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
120
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
121 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
122 av_log(s, AV_LOG_ERROR, "treesize too large\n");
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
123 return -1;
40e81416015d sanity checks some might have been exploitable
michael
parents: 1019
diff changeset
124 }
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 //FIXME remove extradata "rebuilding"
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
127 smk->mmap_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
128 smk->mclr_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
129 smk->full_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
130 smk->type_size = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
131 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
132 smk->rates[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
133 smk->pad = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
134 /* setup data */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
135 if(smk->frames > 0xFFFFFF) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
136 av_log(s, AV_LOG_ERROR, "Too many frames: %i\n", smk->frames);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
137 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
138 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
139 smk->frm_size = av_malloc(smk->frames * 4);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
140 smk->frm_flags = av_malloc(smk->frames);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
141
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
142 smk->is_ver4 = (smk->magic != MKTAG('S', 'M', 'K', '2'));
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
143
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
144 /* read frame info */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
145 for(i = 0; i < smk->frames; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
146 smk->frm_size[i] = get_le32(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
147 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
148 for(i = 0; i < smk->frames; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
149 smk->frm_flags[i] = get_byte(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
150 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
151
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
152 /* init video codec */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
153 st = av_new_stream(s, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
154 if (!st)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
155 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
156 smk->videoindex = st->index;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
157 st->codec->width = smk->width;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
158 st->codec->height = smk->height;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
159 st->codec->pix_fmt = PIX_FMT_PAL8;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
160 st->codec->codec_type = CODEC_TYPE_VIDEO;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
161 st->codec->codec_id = CODEC_ID_SMACKVIDEO;
1089
0319672689ef Now MPlayer should understand Smacker audio and video codecs.
kostya
parents: 1079
diff changeset
162 st->codec->codec_tag = smk->magic;
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
163 /* Smacker uses 100000 as internal timebase */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
164 if(smk->pts_inc < 0)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
165 smk->pts_inc = -smk->pts_inc;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
166 else
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
167 smk->pts_inc *= 100;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
168 tbase = 100000;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
169 av_reduce(&tbase, &smk->pts_inc, tbase, smk->pts_inc, (1UL<<31)-1);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
170 av_set_pts_info(st, 33, smk->pts_inc, tbase);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
171 /* handle possible audio streams */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
172 for(i = 0; i < 7; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
173 smk->indexes[i] = -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
174 if((smk->rates[i] & 0xFFFFFF) && !(smk->rates[i] & SMK_AUD_BINKAUD)){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
175 ast[i] = av_new_stream(s, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
176 smk->indexes[i] = ast[i]->index;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
177 ast[i]->codec->codec_type = CODEC_TYPE_AUDIO;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
178 ast[i]->codec->codec_id = (smk->rates[i] & SMK_AUD_PACKED) ? CODEC_ID_SMACKAUDIO : CODEC_ID_PCM_U8;
1089
0319672689ef Now MPlayer should understand Smacker audio and video codecs.
kostya
parents: 1079
diff changeset
179 ast[i]->codec->codec_tag = MKTAG('S', 'M', 'K', 'A');
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
180 ast[i]->codec->channels = (smk->rates[i] & SMK_AUD_STEREO) ? 2 : 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
181 ast[i]->codec->sample_rate = smk->rates[i] & 0xFFFFFF;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
182 ast[i]->codec->bits_per_sample = (smk->rates[i] & SMK_AUD_16BITS) ? 16 : 8;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
183 if(ast[i]->codec->bits_per_sample == 16 && ast[i]->codec->codec_id == CODEC_ID_PCM_U8)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
184 ast[i]->codec->codec_id = CODEC_ID_PCM_S16LE;
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
185 av_set_pts_info(ast[i], 64, 1, ast[i]->codec->sample_rate
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
186 * ast[i]->codec->channels * ast[i]->codec->bits_per_sample / 8);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
187 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
188 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
189
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
190
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
191 /* load trees to extradata, they will be unpacked by decoder */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
192 st->codec->extradata = av_malloc(smk->treesize + 16);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
193 st->codec->extradata_size = smk->treesize + 16;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
194 if(!st->codec->extradata){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
195 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
196 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
197 av_free(smk->frm_flags);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
198 return -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
199 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
200 ret = get_buffer(pb, st->codec->extradata + 16, st->codec->extradata_size - 16);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
201 if(ret != st->codec->extradata_size - 16){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
202 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
203 av_free(smk->frm_flags);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
204 return AVERROR_IO;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
205 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
206 ((int32_t*)st->codec->extradata)[0] = le2me_32(smk->mmap_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
207 ((int32_t*)st->codec->extradata)[1] = le2me_32(smk->mclr_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
208 ((int32_t*)st->codec->extradata)[2] = le2me_32(smk->full_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
209 ((int32_t*)st->codec->extradata)[3] = le2me_32(smk->type_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
210
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
211 smk->curstream = -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
212 smk->nextpos = url_ftell(pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
213
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
214 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
215 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
216
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
217
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
218 static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
219 {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
220 SmackerContext *smk = (SmackerContext *)s->priv_data;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
221 int flags;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
222 int ret;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
223 int i;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
224 int frame_size = 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
225 int palchange = 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
226 int pos;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
227
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
228 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
229 return AVERROR(EIO);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
230
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
231 /* if we demuxed all streams, pass another frame */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
232 if(smk->curstream < 0) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
233 url_fseek(&s->pb, smk->nextpos, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
234 frame_size = smk->frm_size[smk->cur_frame] & (~3);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
235 flags = smk->frm_flags[smk->cur_frame];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
236 /* handle palette change event */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
237 pos = url_ftell(&s->pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
238 if(flags & SMACKER_PAL){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
239 int size, sz, t, off, j, pos;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
240 uint8_t *pal = smk->pal;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
241 uint8_t oldpal[768];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
242
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
243 memcpy(oldpal, pal, 768);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
244 size = get_byte(&s->pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
245 size = size * 4 - 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
246 frame_size -= size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
247 frame_size--;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
248 sz = 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
249 pos = url_ftell(&s->pb) + size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
250 while(sz < 256){
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
251 t = get_byte(&s->pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
252 if(t & 0x80){ /* skip palette entries */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
253 sz += (t & 0x7F) + 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
254 pal += ((t & 0x7F) + 1) * 3;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
255 } else if(t & 0x40){ /* copy with offset */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
256 off = get_byte(&s->pb) * 3;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
257 j = (t & 0x3F) + 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
258 while(j-- && sz < 256) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
259 *pal++ = oldpal[off + 0];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
260 *pal++ = oldpal[off + 1];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
261 *pal++ = oldpal[off + 2];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
262 sz++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
263 off += 3;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
264 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
265 } else { /* new entries */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
266 *pal++ = smk_pal[t];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
267 *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
268 *pal++ = smk_pal[get_byte(&s->pb) & 0x3F];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
269 sz++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
270 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
271 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
272 url_fseek(&s->pb, pos, 0);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
273 palchange |= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
274 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
275 flags >>= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
276 smk->curstream = -1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
277 /* if audio chunks are present, put them to stack and retrieve later */
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
278 for(i = 0; i < 7; i++) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
279 if(flags & 1) {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
280 int size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
281 size = get_le32(&s->pb) - 4;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
282 frame_size -= size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
283 frame_size -= 4;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
284 smk->curstream++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
285 smk->bufs[smk->curstream] = av_realloc(smk->bufs[smk->curstream], size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
286 smk->buf_sizes[smk->curstream] = size;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
287 ret = get_buffer(&s->pb, smk->bufs[smk->curstream], size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
288 if(ret != size)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
289 return AVERROR_IO;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
290 smk->stream_id[smk->curstream] = smk->indexes[i];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
291 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
292 flags >>= 1;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
293 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
294 if (av_new_packet(pkt, frame_size + 768))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
295 return AVERROR_NOMEM;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
296 if(smk->frm_size[smk->cur_frame] & 1)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
297 palchange |= 2;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
298 pkt->data[0] = palchange;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
299 memcpy(pkt->data + 1, smk->pal, 768);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
300 ret = get_buffer(&s->pb, pkt->data + 769, frame_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
301 if(ret != frame_size)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
302 return AVERROR_IO;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
303 pkt->stream_index = smk->videoindex;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
304 pkt->size = ret + 769;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
305 smk->cur_frame++;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
306 smk->nextpos = url_ftell(&s->pb);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
307 } else {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
308 if (av_new_packet(pkt, smk->buf_sizes[smk->curstream]))
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
309 return AVERROR_NOMEM;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
310 memcpy(pkt->data, smk->bufs[smk->curstream], smk->buf_sizes[smk->curstream]);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
311 pkt->size = smk->buf_sizes[smk->curstream];
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
312 pkt->stream_index = smk->stream_id[smk->curstream];
1090
80b1e60a735e Proper PTS generation for Smacker audio
kostya
parents: 1089
diff changeset
313 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
314 smk->aud_pts[smk->curstream] += AV_RL32(pkt->data);
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
315 smk->curstream--;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
316 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
317
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
318 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
319 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
320
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
321 static int smacker_read_close(AVFormatContext *s)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
322 {
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
323 SmackerContext *smk = (SmackerContext *)s->priv_data;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
324 int i;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
325
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
326 for(i = 0; i < 7; i++)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
327 if(smk->bufs[i])
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
328 av_free(smk->bufs[i]);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
329 if(smk->frm_size)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
330 av_free(smk->frm_size);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
331 if(smk->frm_flags)
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
332 av_free(smk->frm_flags);
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
333
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
334 return 0;
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
335 }
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
336
1169
d18cc9a1fd02 allow individual selection of muxers and demuxers
mru
parents: 1167
diff changeset
337 AVInputFormat smacker_demuxer = {
1019
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
338 "smk",
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
339 "Smacker Video",
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
340 sizeof(SmackerContext),
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
341 smacker_probe,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
342 smacker_read_header,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
343 smacker_read_packet,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
344 smacker_read_close,
a9d8381ff40d Smacker demuxer and decoder.
kostya
parents:
diff changeset
345 };