Mercurial > libavformat.hg
annotate iff.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 |
---|---|
3189 | 1 /* |
3198 | 2 * IFF (.iff) file demuxer |
3189 | 3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> |
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 /** | |
23 * @file iff.c | |
3198 | 24 * IFF file demuxer |
3189 | 25 * by Jaikrishnan Menon |
26 * for more information on the .iff file format, visit: | |
27 * http://wiki.multimedia.cx/index.php?title=IFF | |
28 */ | |
29 | |
30 #include "avformat.h" | |
31 | |
32 #define ID_8SVX MKTAG('8','S','V','X') | |
33 #define ID_VHDR MKTAG('V','H','D','R') | |
34 #define ID_ATAK MKTAG('A','T','A','K') | |
35 #define ID_RLSE MKTAG('R','L','S','E') | |
36 #define ID_CHAN MKTAG('C','H','A','N') | |
37 | |
38 #define ID_FORM MKTAG('F','O','R','M') | |
39 #define ID_ANNO MKTAG('A','N','N','O') | |
40 #define ID_AUTH MKTAG('A','U','T','H') | |
41 #define ID_CHRS MKTAG('C','H','R','S') | |
42 #define ID_COPYRIGHT MKTAG('(','c',')',' ') | |
43 #define ID_CSET MKTAG('C','S','E','T') | |
44 #define ID_FVER MKTAG('F','V','E','R') | |
45 #define ID_NAME MKTAG('N','A','M','E') | |
46 #define ID_TEXT MKTAG('T','E','X','T') | |
47 #define ID_BODY MKTAG('B','O','D','Y') | |
48 | |
49 #define LEFT 2 | |
50 #define RIGHT 4 | |
51 #define STEREO 6 | |
52 | |
53 #define PACKET_SIZE 1024 | |
54 | |
55 typedef enum {COMP_NONE, COMP_FIB, COMP_EXP} svx8_compression_t; | |
56 | |
57 typedef struct { | |
58 uint32_t body_size; | |
59 uint32_t sent_bytes; | |
60 uint32_t audio_frame_count; | |
61 } IffDemuxContext; | |
62 | |
3285 | 63 |
64 static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size) | |
65 { | |
66 uint8_t *end = dest + size; | |
67 size = size>>1; | |
68 | |
69 while(dest < end) { | |
70 *dest++ = *src; | |
71 *dest++ = *(src+size); | |
72 src++; | |
73 } | |
74 } | |
75 | |
3189 | 76 static int iff_probe(AVProbeData *p) |
77 { | |
78 const uint8_t *d = p->buf; | |
79 | |
80 if ( AV_RL32(d) == ID_FORM && | |
81 AV_RL32(d+8) == ID_8SVX) | |
82 return AVPROBE_SCORE_MAX; | |
83 return 0; | |
84 } | |
85 | |
86 static int iff_read_header(AVFormatContext *s, | |
87 AVFormatParameters *ap) | |
88 { | |
89 IffDemuxContext *iff = s->priv_data; | |
90 ByteIOContext *pb = s->pb; | |
91 AVStream *st; | |
92 uint32_t chunk_id, data_size; | |
3200 | 93 int padding, done = 0; |
3189 | 94 |
95 st = av_new_stream(s, 0); | |
96 if (!st) | |
97 return AVERROR(ENOMEM); | |
98 | |
99 st->codec->channels = 1; | |
100 url_fskip(pb, 12); | |
101 | |
102 while(!done && !url_feof(pb)) { | |
103 chunk_id = get_le32(pb); | |
104 data_size = get_be32(pb); | |
105 padding = data_size & 1; | |
106 | |
107 switch(chunk_id) { | |
108 case ID_VHDR: | |
109 url_fskip(pb, 12); | |
110 st->codec->sample_rate = get_be16(pb); | |
111 url_fskip(pb, 1); | |
112 st->codec->codec_tag = get_byte(pb); | |
113 url_fskip(pb, 4); | |
114 break; | |
115 | |
116 case ID_BODY: | |
117 iff->body_size = data_size; | |
118 done = 1; | |
119 break; | |
120 | |
121 case ID_CHAN: | |
122 st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; | |
123 break; | |
124 | |
125 default: | |
126 url_fseek(pb, data_size + padding, SEEK_CUR); | |
127 break; | |
128 } | |
129 } | |
130 | |
131 if(!st->codec->sample_rate) | |
132 return AVERROR_INVALIDDATA; | |
133 | |
134 av_set_pts_info(st, 32, 1, st->codec->sample_rate); | |
135 st->codec->codec_type = CODEC_TYPE_AUDIO; | |
136 | |
137 switch(st->codec->codec_tag) { | |
138 case COMP_NONE: | |
139 st->codec->codec_id = CODEC_ID_PCM_S8; | |
140 break; | |
141 case COMP_FIB: | |
142 st->codec->codec_id = CODEC_ID_8SVX_FIB; | |
143 break; | |
144 case COMP_EXP: | |
145 st->codec->codec_id = CODEC_ID_8SVX_EXP; | |
146 break; | |
147 default: | |
148 av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n"); | |
149 return -1; | |
150 } | |
151 | |
152 st->codec->bits_per_sample = 8; | |
153 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_sample; | |
154 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; | |
155 | |
156 return 0; | |
157 } | |
158 | |
159 static int iff_read_packet(AVFormatContext *s, | |
160 AVPacket *pkt) | |
161 { | |
162 IffDemuxContext *iff = s->priv_data; | |
163 ByteIOContext *pb = s->pb; | |
164 int ret; | |
165 | |
166 if(iff->sent_bytes > iff->body_size) | |
167 return AVERROR(EIO); | |
3285 | 168 |
169 if(s->streams[0]->codec->channels == 2) { | |
170 uint8_t sample_buffer[PACKET_SIZE]; | |
171 | |
172 ret = get_buffer(pb, sample_buffer, PACKET_SIZE); | |
173 if(av_new_packet(pkt, PACKET_SIZE) < 0) { | |
174 av_log(s, AV_LOG_ERROR, "iff: cannot allocate packet \n"); | |
175 return AVERROR(ENOMEM); | |
176 } | |
177 interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE); | |
178 } | |
179 else { | |
180 ret = av_get_packet(pb, pkt, PACKET_SIZE); | |
181 } | |
3189 | 182 |
183 if(iff->sent_bytes == 0) | |
184 pkt->flags |= PKT_FLAG_KEY; | |
185 | |
186 iff->sent_bytes += PACKET_SIZE; | |
187 pkt->stream_index = 0; | |
188 pkt->pts = iff->audio_frame_count; | |
189 iff->audio_frame_count += ret / s->streams[0]->codec->channels; | |
190 return ret; | |
191 } | |
192 | |
193 AVInputFormat iff_demuxer = { | |
194 "IFF", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3285
diff
changeset
|
195 NULL_IF_CONFIG_SMALL("IFF format"), |
3189 | 196 sizeof(IffDemuxContext), |
197 iff_probe, | |
198 iff_read_header, | |
199 iff_read_packet, | |
200 }; |