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