Mercurial > libavformat.hg
annotate iff.c @ 5976:e46f8cc350ef libavformat
Fix MTV decoding on big-endian systems
author | vitor |
---|---|
date | Wed, 21 Apr 2010 13:00:48 +0000 |
parents | 43548500ffbc |
children | 55c714a8fb00 |
rev | line source |
---|---|
3189 | 1 /* |
3198 | 2 * IFF (.iff) file demuxer |
3189 | 3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> |
5625 | 4 * Copyright (c) 2010 Peter Ross <pross@xvid.org> |
3189 | 5 * |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 /** | |
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5913
diff
changeset
|
24 * @file |
3198 | 25 * IFF file demuxer |
3189 | 26 * by Jaikrishnan Menon |
27 * for more information on the .iff file format, visit: | |
28 * http://wiki.multimedia.cx/index.php?title=IFF | |
29 */ | |
30 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
4090
diff
changeset
|
31 #include "libavutil/intreadwrite.h" |
5773
fd3b7b9b63a8
IFF: move ff_cmap_read_palette() prototype to a header file
mru
parents:
5660
diff
changeset
|
32 #include "libavcodec/iff.h" |
3189 | 33 #include "avformat.h" |
34 | |
35 #define ID_8SVX MKTAG('8','S','V','X') | |
36 #define ID_VHDR MKTAG('V','H','D','R') | |
37 #define ID_ATAK MKTAG('A','T','A','K') | |
38 #define ID_RLSE MKTAG('R','L','S','E') | |
39 #define ID_CHAN MKTAG('C','H','A','N') | |
5625 | 40 #define ID_PBM MKTAG('P','B','M',' ') |
41 #define ID_ILBM MKTAG('I','L','B','M') | |
42 #define ID_BMHD MKTAG('B','M','H','D') | |
43 #define ID_CMAP MKTAG('C','M','A','P') | |
3189 | 44 |
45 #define ID_FORM MKTAG('F','O','R','M') | |
46 #define ID_ANNO MKTAG('A','N','N','O') | |
47 #define ID_AUTH MKTAG('A','U','T','H') | |
48 #define ID_CHRS MKTAG('C','H','R','S') | |
49 #define ID_COPYRIGHT MKTAG('(','c',')',' ') | |
50 #define ID_CSET MKTAG('C','S','E','T') | |
51 #define ID_FVER MKTAG('F','V','E','R') | |
52 #define ID_NAME MKTAG('N','A','M','E') | |
53 #define ID_TEXT MKTAG('T','E','X','T') | |
54 #define ID_BODY MKTAG('B','O','D','Y') | |
5660 | 55 #define ID_ANNO MKTAG('A','N','N','O') |
3189 | 56 |
57 #define LEFT 2 | |
58 #define RIGHT 4 | |
59 #define STEREO 6 | |
60 | |
61 #define PACKET_SIZE 1024 | |
62 | |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
63 typedef enum { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
64 COMP_NONE, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
65 COMP_FIB, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
66 COMP_EXP |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
67 } svx8_compression_type; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
68 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
69 typedef enum { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
70 BITMAP_RAW, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
71 BITMAP_BYTERUN1 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
72 } bitmap_compression_type; |
3189 | 73 |
74 typedef struct { | |
75 uint32_t body_size; | |
76 uint32_t sent_bytes; | |
77 uint32_t audio_frame_count; | |
78 } IffDemuxContext; | |
79 | |
3285 | 80 |
81 static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size) | |
82 { | |
83 uint8_t *end = dest + size; | |
84 size = size>>1; | |
85 | |
86 while(dest < end) { | |
87 *dest++ = *src; | |
88 *dest++ = *(src+size); | |
89 src++; | |
90 } | |
91 } | |
92 | |
3189 | 93 static int iff_probe(AVProbeData *p) |
94 { | |
95 const uint8_t *d = p->buf; | |
96 | |
97 if ( AV_RL32(d) == ID_FORM && | |
5625 | 98 (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_PBM || AV_RL32(d+8) == ID_ILBM) ) |
3189 | 99 return AVPROBE_SCORE_MAX; |
100 return 0; | |
101 } | |
102 | |
103 static int iff_read_header(AVFormatContext *s, | |
104 AVFormatParameters *ap) | |
105 { | |
106 IffDemuxContext *iff = s->priv_data; | |
107 ByteIOContext *pb = s->pb; | |
108 AVStream *st; | |
109 uint32_t chunk_id, data_size; | |
3200 | 110 int padding, done = 0; |
5625 | 111 int compression = -1; |
5660 | 112 char *buf; |
3189 | 113 |
114 st = av_new_stream(s, 0); | |
115 if (!st) | |
116 return AVERROR(ENOMEM); | |
117 | |
118 st->codec->channels = 1; | |
5625 | 119 url_fskip(pb, 8); |
120 // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content | |
121 st->codec->codec_tag = get_le32(pb); | |
3189 | 122 |
123 while(!done && !url_feof(pb)) { | |
124 chunk_id = get_le32(pb); | |
125 data_size = get_be32(pb); | |
126 padding = data_size & 1; | |
127 | |
128 switch(chunk_id) { | |
129 case ID_VHDR: | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
130 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
3189 | 131 url_fskip(pb, 12); |
132 st->codec->sample_rate = get_be16(pb); | |
133 url_fskip(pb, 1); | |
5625 | 134 compression = get_byte(pb); |
3189 | 135 url_fskip(pb, 4); |
136 break; | |
137 | |
138 case ID_BODY: | |
139 iff->body_size = data_size; | |
140 done = 1; | |
141 break; | |
142 | |
143 case ID_CHAN: | |
144 st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; | |
145 break; | |
146 | |
5625 | 147 case ID_CMAP: |
148 st->codec->extradata_size = data_size; | |
149 st->codec->extradata = av_malloc(data_size); | |
150 if (!st->codec->extradata) | |
151 return AVERROR(ENOMEM); | |
152 if (get_buffer(pb, st->codec->extradata, data_size) < 0) | |
153 return AVERROR(EIO); | |
154 break; | |
155 | |
156 case ID_BMHD: | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
157 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
5625 | 158 st->codec->width = get_be16(pb); |
159 st->codec->height = get_be16(pb); | |
160 url_fskip(pb, 4); // x, y offset | |
161 st->codec->bits_per_coded_sample = get_byte(pb); | |
162 url_fskip(pb, 1); // masking | |
163 compression = get_byte(pb); | |
164 url_fskip(pb, 3); // paddding, transparent | |
165 st->sample_aspect_ratio.num = get_byte(pb); | |
166 st->sample_aspect_ratio.den = get_byte(pb); | |
167 url_fskip(pb, 4); // source page width, height | |
168 break; | |
169 | |
5660 | 170 case ID_ANNO: |
171 buf = av_malloc(data_size + 1); | |
172 if (!buf) | |
173 break; | |
174 get_buffer(pb, buf, data_size); | |
175 buf[data_size] = 0; | |
176 av_metadata_set2(&s->metadata, "comment", buf, AV_METADATA_DONT_STRDUP_VAL); | |
177 break; | |
178 | |
3189 | 179 default: |
180 url_fseek(pb, data_size + padding, SEEK_CUR); | |
181 break; | |
182 } | |
183 } | |
184 | |
5625 | 185 switch(st->codec->codec_type) { |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
186 case AVMEDIA_TYPE_AUDIO: |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
187 av_set_pts_info(st, 32, 1, st->codec->sample_rate); |
3189 | 188 |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
189 switch(compression) { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
190 case COMP_NONE: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
191 st->codec->codec_id = CODEC_ID_PCM_S8; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
192 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
193 case COMP_FIB: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
194 st->codec->codec_id = CODEC_ID_8SVX_FIB; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
195 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
196 case COMP_EXP: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
197 st->codec->codec_id = CODEC_ID_8SVX_EXP; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
198 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
199 default: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
200 av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n"); |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
201 return -1; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
202 } |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
203 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
204 st->codec->bits_per_coded_sample = 8; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
205 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
206 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; |
3189 | 207 break; |
5625 | 208 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
209 case AVMEDIA_TYPE_VIDEO: |
5625 | 210 switch (compression) { |
211 case BITMAP_RAW: | |
212 if (st->codec->codec_tag == ID_ILBM) { | |
213 st->codec->codec_id = CODEC_ID_IFF_ILBM; | |
214 } else { | |
215 st->codec->codec_id = CODEC_ID_RAWVIDEO; | |
216 st->codec->pix_fmt = PIX_FMT_PAL8; | |
217 st->codec->codec_tag = 0; | |
218 } | |
219 break; | |
220 case BITMAP_BYTERUN1: | |
221 st->codec->codec_id = CODEC_ID_IFF_BYTERUN1; | |
222 break; | |
223 default: | |
224 av_log(s, AV_LOG_ERROR, "unknown compression method\n"); | |
225 return AVERROR_INVALIDDATA; | |
226 } | |
227 break; | |
228 default: | |
229 return -1; | |
230 } | |
3189 | 231 |
232 return 0; | |
233 } | |
234 | |
235 static int iff_read_packet(AVFormatContext *s, | |
236 AVPacket *pkt) | |
237 { | |
238 IffDemuxContext *iff = s->priv_data; | |
239 ByteIOContext *pb = s->pb; | |
5625 | 240 AVStream *st = s->streams[0]; |
3189 | 241 int ret; |
242 | |
5625 | 243 if(iff->sent_bytes >= iff->body_size) |
3189 | 244 return AVERROR(EIO); |
3285 | 245 |
246 if(s->streams[0]->codec->channels == 2) { | |
247 uint8_t sample_buffer[PACKET_SIZE]; | |
248 | |
249 ret = get_buffer(pb, sample_buffer, PACKET_SIZE); | |
250 if(av_new_packet(pkt, PACKET_SIZE) < 0) { | |
251 av_log(s, AV_LOG_ERROR, "iff: cannot allocate packet \n"); | |
252 return AVERROR(ENOMEM); | |
253 } | |
254 interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE); | |
5625 | 255 } else if (s->streams[0]->codec->codec_id == CODEC_ID_RAWVIDEO) { |
256 if(av_new_packet(pkt, iff->body_size + AVPALETTE_SIZE) < 0) { | |
257 return AVERROR(ENOMEM); | |
258 } | |
259 | |
260 ret = ff_cmap_read_palette(st->codec, (uint32_t*)(pkt->data + iff->body_size)); | |
261 if (ret < 0) | |
262 return ret; | |
263 av_freep(&st->codec->extradata); | |
264 st->codec->extradata_size = 0; | |
265 | |
266 ret = get_buffer(pb, pkt->data, iff->body_size); | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
267 } else if (s->streams[0]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
5625 | 268 ret = av_get_packet(pb, pkt, iff->body_size); |
269 } else { | |
3285 | 270 ret = av_get_packet(pb, pkt, PACKET_SIZE); |
271 } | |
3189 | 272 |
273 if(iff->sent_bytes == 0) | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
274 pkt->flags |= AV_PKT_FLAG_KEY; |
3189 | 275 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
276 if(s->streams[0]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
5626 | 277 iff->sent_bytes += PACKET_SIZE; |
5625 | 278 } else { |
279 iff->sent_bytes = iff->body_size; | |
280 } | |
3189 | 281 pkt->stream_index = 0; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
282 if(s->streams[0]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
5626 | 283 pkt->pts = iff->audio_frame_count; |
284 iff->audio_frame_count += ret / s->streams[0]->codec->channels; | |
5625 | 285 } |
3189 | 286 return ret; |
287 } | |
288 | |
289 AVInputFormat iff_demuxer = { | |
290 "IFF", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3285
diff
changeset
|
291 NULL_IF_CONFIG_SMALL("IFF format"), |
3189 | 292 sizeof(IffDemuxContext), |
293 iff_probe, | |
294 iff_read_header, | |
295 iff_read_packet, | |
296 }; |