Mercurial > libavformat.hg
annotate siff.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 7a0230981402 |
children | 1d3d17de20ba |
rev | line source |
---|---|
2659 | 1 /* |
2 * Beam Software SIFF demuxer | |
3 * Copyright (c) 2007 Konstantin Shishkov. | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 #include "avformat.h" | |
23 | |
24 enum SIFFTags{ | |
25 TAG_SIFF = MKTAG('S', 'I', 'F', 'F'), | |
26 TAG_BODY = MKTAG('B', 'O', 'D', 'Y'), | |
27 TAG_VBHD = MKTAG('V', 'B', 'H', 'D'), | |
28 TAG_SHDR = MKTAG('S', 'H', 'D', 'R'), | |
29 TAG_VBV1 = MKTAG('V', 'B', 'V', '1'), | |
30 TAG_SOUN = MKTAG('S', 'O', 'U', 'N'), | |
31 }; | |
32 | |
33 enum VBFlags{ | |
34 VB_HAS_GMC = 0x01, | |
35 VB_HAS_AUDIO = 0x04, | |
36 VB_HAS_VIDEO = 0x08, | |
37 VB_HAS_PALETTE = 0x10, | |
38 VB_HAS_LENGTH = 0x20 | |
39 }; | |
40 | |
41 typedef struct SIFFContext{ | |
42 int frames; | |
43 int cur_frame; | |
44 int rate; | |
45 int bits; | |
46 int block_align; | |
47 | |
48 int has_video; | |
49 int has_audio; | |
50 | |
51 int curstrm; | |
52 int pktsize; | |
53 int gmcsize; | |
54 int sndsize; | |
55 | |
56 int flags; | |
57 uint8_t gmc[4]; | |
58 }SIFFContext; | |
59 | |
60 static int siff_probe(AVProbeData *p) | |
61 { | |
62 /* check file header */ | |
63 if (AV_RL32(p->buf) == TAG_SIFF) | |
64 return AVPROBE_SCORE_MAX; | |
65 else | |
66 return 0; | |
67 } | |
68 | |
69 static int create_audio_stream(AVFormatContext *s, SIFFContext *c) | |
70 { | |
71 AVStream *ast; | |
72 ast = av_new_stream(s, 0); | |
73 if (!ast) | |
74 return -1; | |
75 ast->codec->codec_type = CODEC_TYPE_AUDIO; | |
76 ast->codec->codec_id = CODEC_ID_PCM_U8; | |
77 ast->codec->channels = 1; | |
78 ast->codec->bits_per_sample = c->bits; | |
79 ast->codec->sample_rate = c->rate; | |
80 ast->codec->frame_size = c->block_align; | |
81 av_set_pts_info(ast, 16, 1, c->rate); | |
82 return 0; | |
83 } | |
84 | |
85 static int siff_parse_vbv1(AVFormatContext *s, SIFFContext *c, ByteIOContext *pb) | |
86 { | |
87 AVStream *st; | |
88 int width, height; | |
89 | |
90 if (get_le32(pb) != TAG_VBHD){ | |
91 av_log(s, AV_LOG_ERROR, "Header chunk is missing\n"); | |
92 return -1; | |
93 } | |
94 if(get_be32(pb) != 32){ | |
95 av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n"); | |
96 return -1; | |
97 } | |
98 if(get_le16(pb) != 1){ | |
99 av_log(s, AV_LOG_ERROR, "Incorrect header version\n"); | |
100 return -1; | |
101 } | |
102 width = get_le16(pb); | |
103 height = get_le16(pb); | |
104 url_fskip(pb, 4); | |
105 c->frames = get_le16(pb); | |
106 if(!c->frames){ | |
107 av_log(s, AV_LOG_ERROR, "File contains no frames ???\n"); | |
108 return -1; | |
109 } | |
110 c->bits = get_le16(pb); | |
111 c->rate = get_le16(pb); | |
112 c->block_align = c->rate * (c->bits >> 3); | |
113 | |
114 url_fskip(pb, 16); //zeroes | |
115 | |
116 st = av_new_stream(s, 0); | |
117 if (!st) | |
118 return -1; | |
119 st->codec->codec_type = CODEC_TYPE_VIDEO; | |
120 st->codec->codec_id = CODEC_ID_VB; | |
121 st->codec->codec_tag = MKTAG('V', 'B', 'V', '1'); | |
122 st->codec->width = width; | |
123 st->codec->height = height; | |
124 st->codec->pix_fmt = PIX_FMT_PAL8; | |
125 av_set_pts_info(st, 16, 1, 12); | |
126 | |
127 c->cur_frame = 0; | |
128 c->has_video = 1; | |
129 c->has_audio = !!c->rate; | |
130 c->curstrm = -1; | |
131 if (c->has_audio && create_audio_stream(s, c) < 0) | |
132 return -1; | |
133 return 0; | |
134 } | |
135 | |
136 static int siff_parse_soun(AVFormatContext *s, SIFFContext *c, ByteIOContext *pb) | |
137 { | |
138 if (get_le32(pb) != TAG_SHDR){ | |
139 av_log(s, AV_LOG_ERROR, "Header chunk is missing\n"); | |
140 return -1; | |
141 } | |
142 if(get_be32(pb) != 8){ | |
143 av_log(s, AV_LOG_ERROR, "Header chunk size is incorrect\n"); | |
144 return -1; | |
145 } | |
146 url_fskip(pb, 4); //unknown value | |
147 c->rate = get_le16(pb); | |
148 c->bits = get_le16(pb); | |
149 c->block_align = c->rate * (c->bits >> 3); | |
150 return create_audio_stream(s, c); | |
151 } | |
152 | |
153 static int siff_read_header(AVFormatContext *s, AVFormatParameters *ap) | |
154 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
155 ByteIOContext *pb = s->pb; |
2659 | 156 SIFFContext *c = s->priv_data; |
157 uint32_t tag; | |
158 | |
159 if (get_le32(pb) != TAG_SIFF) | |
160 return -1; | |
161 url_fskip(pb, 4); //ignore size | |
162 tag = get_le32(pb); | |
163 | |
164 if (tag != TAG_VBV1 && tag != TAG_SOUN){ | |
165 av_log(s, AV_LOG_ERROR, "Not a VBV file\n"); | |
166 return -1; | |
167 } | |
168 | |
169 if (tag == TAG_VBV1 && siff_parse_vbv1(s, c, pb) < 0) | |
170 return -1; | |
171 if (tag == TAG_SOUN && siff_parse_soun(s, c, pb) < 0) | |
172 return -1; | |
173 if (get_le32(pb) != MKTAG('B', 'O', 'D', 'Y')){ | |
174 av_log(s, AV_LOG_ERROR, "'BODY' chunk is missing\n"); | |
175 return -1; | |
176 } | |
177 url_fskip(pb, 4); //ignore size | |
178 | |
179 return 0; | |
180 } | |
181 | |
182 static int siff_read_packet(AVFormatContext *s, AVPacket *pkt) | |
183 { | |
184 SIFFContext *c = s->priv_data; | |
2690
0a8f2dc62d01
Remove unused variables, fixes the following warnings:
diego
parents:
2659
diff
changeset
|
185 int size; |
2659 | 186 |
187 if (c->has_video){ | |
188 if (c->cur_frame >= c->frames) | |
189 return AVERROR(EIO); | |
190 if (c->curstrm == -1){ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
191 c->pktsize = get_le32(s->pb) - 4; |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
192 c->flags = get_le16(s->pb); |
2659 | 193 c->gmcsize = (c->flags & VB_HAS_GMC) ? 4 : 0; |
194 if (c->gmcsize) | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
195 get_buffer(s->pb, c->gmc, c->gmcsize); |
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
196 c->sndsize = (c->flags & VB_HAS_AUDIO) ? get_le32(s->pb): 0; |
2659 | 197 c->curstrm = !!(c->flags & VB_HAS_AUDIO); |
198 } | |
199 | |
200 if (!c->curstrm){ | |
201 size = c->pktsize - c->sndsize; | |
202 if (av_new_packet(pkt, size) < 0) | |
203 return AVERROR(ENOMEM); | |
204 AV_WL16(pkt->data, c->flags); | |
205 if (c->gmcsize) | |
206 memcpy(pkt->data + 2, c->gmc, c->gmcsize); | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
207 get_buffer(s->pb, pkt->data + 2 + c->gmcsize, size - c->gmcsize - 2); |
2659 | 208 pkt->stream_index = 0; |
209 c->curstrm = -1; | |
210 }else{ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
211 if (av_get_packet(s->pb, pkt, c->sndsize - 4) < 0) |
2659 | 212 return AVERROR(EIO); |
213 pkt->stream_index = 1; | |
214 c->curstrm = 0; | |
215 } | |
216 if(!c->cur_frame || c->curstrm) | |
217 pkt->flags |= PKT_FLAG_KEY; | |
218 if (c->curstrm == -1) | |
219 c->cur_frame++; | |
220 }else{ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2690
diff
changeset
|
221 size = av_get_packet(s->pb, pkt, c->block_align); |
2659 | 222 if(size <= 0) |
223 return AVERROR(EIO); | |
224 } | |
225 return pkt->size; | |
226 } | |
227 | |
228 AVInputFormat siff_demuxer = { | |
229 "siff", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3399
diff
changeset
|
230 NULL_IF_CONFIG_SMALL("Beam Software SIFF"), |
2659 | 231 sizeof(SIFFContext), |
232 siff_probe, | |
233 siff_read_header, | |
234 siff_read_packet, | |
235 .extensions = "vb,son" | |
236 }; |