Mercurial > libavformat.hg
annotate wv.c @ 5966:9a86b49201bb libavformat
Revert svn rev 21857, readd first_rtcp_ntp_time in RTPDemuxContext
In order to sync RTP streams that get their initial RTCP timestamp at
different times, propagate the NTP timestamp of the first RTCP packet
to all other streams.
This makes the timestamps of returned packets start at (near) zero instead
of at any random offset.
author | mstorsjo |
---|---|
date | Tue, 20 Apr 2010 07:34:28 +0000 |
parents | 536e5527c1e0 |
children |
rev | line source |
---|---|
1324 | 1 /* |
2 * WavPack demuxer | |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4237
diff
changeset
|
3 * Copyright (c) 2006 Konstantin Shishkov |
1324 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
1324 | 8 * modify it under the terms of the GNU Lesser General Public |
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:
1324
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
1324 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
1324 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1324
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
1324 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | |
21 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3908
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
1324 | 23 #include "avformat.h" |
5300 | 24 #include "apetag.h" |
25 #include "id3v1.h" | |
1324 | 26 |
27 // specs say that maximum block size is 1Mb | |
28 #define WV_BLOCK_LIMIT 1047576 | |
29 | |
30 #define WV_EXTRA_SIZE 12 | |
31 | |
32 enum WV_FLAGS{ | |
33 WV_MONO = 0x0004, | |
34 WV_HYBRID = 0x0008, | |
35 WV_JOINT = 0x0010, | |
36 WV_CROSSD = 0x0020, | |
37 WV_HSHAPE = 0x0040, | |
38 WV_FLOAT = 0x0080, | |
39 WV_INT32 = 0x0100, | |
40 WV_HBR = 0x0200, | |
41 WV_HBAL = 0x0400, | |
42 WV_MCINIT = 0x0800, | |
43 WV_MCEND = 0x1000, | |
44 }; | |
45 | |
46 static const int wv_rates[16] = { | |
47 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, | |
48 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 | |
49 }; | |
50 | |
51 typedef struct{ | |
52 uint32_t blksize, flags; | |
53 int rate, chan, bpp; | |
1743 | 54 uint32_t samples, soff; |
1324 | 55 int block_parsed; |
56 uint8_t extra[WV_EXTRA_SIZE]; | |
1743 | 57 int64_t pos; |
1324 | 58 }WVContext; |
59 | |
60 static int wv_probe(AVProbeData *p) | |
61 { | |
62 /* check file header */ | |
63 if (p->buf_size <= 32) | |
64 return 0; | |
65 if (p->buf[0] == 'w' && p->buf[1] == 'v' && | |
66 p->buf[2] == 'p' && p->buf[3] == 'k') | |
67 return AVPROBE_SCORE_MAX; | |
68 else | |
69 return 0; | |
70 } | |
71 | |
72 static int wv_read_block_header(AVFormatContext *ctx, ByteIOContext *pb) | |
73 { | |
74 WVContext *wc = ctx->priv_data; | |
75 uint32_t tag, ver; | |
76 int size; | |
77 int rate, bpp, chan; | |
78 | |
1743 | 79 wc->pos = url_ftell(pb); |
1324 | 80 tag = get_le32(pb); |
81 if (tag != MKTAG('w', 'v', 'p', 'k')) | |
82 return -1; | |
83 size = get_le32(pb); | |
84 if(size < 24 || size > WV_BLOCK_LIMIT){ | |
85 av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size); | |
86 return -1; | |
87 } | |
88 wc->blksize = size; | |
89 ver = get_le16(pb); | |
2380
41c9871ea3c4
Support for WavPack version 0x410 (false stereo chunks)
kostya
parents:
2314
diff
changeset
|
90 if(ver < 0x402 || ver > 0x410){ |
1324 | 91 av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver); |
92 return -1; | |
93 } | |
94 get_byte(pb); // track no | |
95 get_byte(pb); // track sub index | |
1743 | 96 wc->samples = get_le32(pb); // total samples in file |
97 wc->soff = get_le32(pb); // offset in samples of current block | |
1324 | 98 get_buffer(pb, wc->extra, WV_EXTRA_SIZE); |
1673 | 99 wc->flags = AV_RL32(wc->extra + 4); |
1324 | 100 //parse flags |
101 bpp = ((wc->flags & 3) + 1) << 3; | |
102 chan = 1 + !(wc->flags & WV_MONO); | |
103 rate = wv_rates[(wc->flags >> 23) & 0xF]; | |
5350
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
104 if(rate == -1 && !wc->block_parsed){ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
105 int64_t block_end = url_ftell(pb) + wc->blksize - 24; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
106 if(url_is_streamed(pb)){ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
107 av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n"); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
108 return -1; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
109 } |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
110 while(url_ftell(pb) < block_end){ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
111 int id, size; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
112 id = get_byte(pb); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
113 size = (id & 0x80) ? get_le24(pb) : get_byte(pb); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
114 size <<= 1; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
115 if(id&0x40) |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
116 size--; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
117 if((id&0x3F) == 0x27){ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
118 rate = get_le24(pb); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
119 break; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
120 }else{ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
121 url_fskip(pb, size); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
122 } |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
123 } |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
124 if(rate == -1){ |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
125 av_log(ctx, AV_LOG_ERROR, "Cannot determine custom sampling rate\n"); |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
126 return -1; |
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
127 } |
5353
70956fb584b3
10l: WavPack demuxer forgot to seek back to initial position after block
kostya
parents:
5350
diff
changeset
|
128 url_fseek(pb, block_end - wc->blksize + 24, SEEK_SET); |
1324 | 129 } |
130 if(!wc->bpp) wc->bpp = bpp; | |
131 if(!wc->chan) wc->chan = chan; | |
132 if(!wc->rate) wc->rate = rate; | |
133 | |
1389
9ed80abc8eb7
Ignore blocks with no samples and flags (but usually with MD5 sum)
kostya
parents:
1387
diff
changeset
|
134 if(wc->flags && bpp != wc->bpp){ |
1324 | 135 av_log(ctx, AV_LOG_ERROR, "Bits per sample differ, this block: %i, header block: %i\n", bpp, wc->bpp); |
136 return -1; | |
137 } | |
1389
9ed80abc8eb7
Ignore blocks with no samples and flags (but usually with MD5 sum)
kostya
parents:
1387
diff
changeset
|
138 if(wc->flags && chan != wc->chan){ |
1324 | 139 av_log(ctx, AV_LOG_ERROR, "Channels differ, this block: %i, header block: %i\n", chan, wc->chan); |
140 return -1; | |
141 } | |
5350
e5805e11f596
If custom sampling rate is set in WavPack file, parse first block to find
kostya
parents:
5349
diff
changeset
|
142 if(wc->flags && rate != -1 && rate != wc->rate){ |
1324 | 143 av_log(ctx, AV_LOG_ERROR, "Sampling rate differ, this block: %i, header block: %i\n", rate, wc->rate); |
144 return -1; | |
145 } | |
146 wc->blksize = size - 24; | |
147 return 0; | |
148 } | |
149 | |
150 static int wv_read_header(AVFormatContext *s, | |
151 AVFormatParameters *ap) | |
152 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
153 ByteIOContext *pb = s->pb; |
1324 | 154 WVContext *wc = s->priv_data; |
155 AVStream *st; | |
156 | |
5349
d2cdd13aacff
Initialize block_parsed before reading first block header in WavPack demuxer,
kostya
parents:
5300
diff
changeset
|
157 wc->block_parsed = 0; |
1324 | 158 if(wv_read_block_header(s, pb) < 0) |
159 return -1; | |
160 | |
161 /* now we are ready: build format streams */ | |
162 st = av_new_stream(s, 0); | |
163 if (!st) | |
164 return -1; | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5566
diff
changeset
|
165 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
1324 | 166 st->codec->codec_id = CODEC_ID_WAVPACK; |
167 st->codec->channels = wc->chan; | |
168 st->codec->sample_rate = wc->rate; | |
3908
1d3d17de20ba
Bump Major version, this commit is almost just renaming bits_per_sample to
michael
parents:
3482
diff
changeset
|
169 st->codec->bits_per_coded_sample = wc->bpp; |
1324 | 170 av_set_pts_info(st, 64, 1, wc->rate); |
5566
28094e9bd013
Set start_time and duration in AVStream instead of AVFormatContext for
conrad
parents:
5353
diff
changeset
|
171 st->start_time = 0; |
28094e9bd013
Set start_time and duration in AVStream instead of AVFormatContext for
conrad
parents:
5353
diff
changeset
|
172 st->duration = wc->samples; |
5300 | 173 |
174 if(!url_is_streamed(s->pb)) { | |
175 int64_t cur = url_ftell(s->pb); | |
176 ff_ape_parse_tag(s); | |
177 if(!av_metadata_get(s->metadata, "", NULL, AV_METADATA_IGNORE_SUFFIX)) | |
178 ff_id3v1_read(s); | |
179 url_fseek(s->pb, cur, SEEK_SET); | |
180 } | |
181 | |
1324 | 182 return 0; |
183 } | |
184 | |
185 static int wv_read_packet(AVFormatContext *s, | |
186 AVPacket *pkt) | |
187 { | |
188 WVContext *wc = s->priv_data; | |
1391 | 189 int ret; |
1324 | 190 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
191 if (url_feof(s->pb)) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1743
diff
changeset
|
192 return AVERROR(EIO); |
1324 | 193 if(wc->block_parsed){ |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
194 if(wv_read_block_header(s, s->pb) < 0) |
1324 | 195 return -1; |
196 } | |
197 | |
198 if(av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE) < 0) | |
2273
7eb456c4ed8a
Replace all occurrences of AVERROR_NOMEM with AVERROR(ENOMEM).
takis
parents:
1787
diff
changeset
|
199 return AVERROR(ENOMEM); |
1324 | 200 memcpy(pkt->data, wc->extra, WV_EXTRA_SIZE); |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
201 ret = get_buffer(s->pb, pkt->data + WV_EXTRA_SIZE, wc->blksize); |
1324 | 202 if(ret != wc->blksize){ |
203 av_free_packet(pkt); | |
2274
b21c2af60bc9
Replace all occurrences of AVERROR_IO with AVERROR(EIO).
takis
parents:
2273
diff
changeset
|
204 return AVERROR(EIO); |
1324 | 205 } |
206 pkt->stream_index = 0; | |
207 wc->block_parsed = 1; | |
208 pkt->size = ret + WV_EXTRA_SIZE; | |
1743 | 209 pkt->pts = wc->soff; |
210 av_add_index_entry(s->streams[0], wc->pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); | |
1324 | 211 return 0; |
212 } | |
213 | |
1743 | 214 static int wv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
215 { | |
216 AVStream *st = s->streams[stream_index]; | |
217 WVContext *wc = s->priv_data; | |
218 AVPacket pkt1, *pkt = &pkt1; | |
219 int ret; | |
220 int index = av_index_search_timestamp(st, timestamp, flags); | |
221 int64_t pos, pts; | |
222 | |
223 /* if found, seek there */ | |
224 if (index >= 0){ | |
225 wc->block_parsed = 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
226 url_fseek(s->pb, st->index_entries[index].pos, SEEK_SET); |
1743 | 227 return 0; |
228 } | |
229 /* if timestamp is out of bounds, return error */ | |
230 if(timestamp < 0 || timestamp >= s->duration) | |
231 return -1; | |
232 | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
233 pos = url_ftell(s->pb); |
1743 | 234 do{ |
235 ret = av_read_frame(s, pkt); | |
236 if (ret < 0){ | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2555
diff
changeset
|
237 url_fseek(s->pb, pos, SEEK_SET); |
1743 | 238 return -1; |
239 } | |
240 pts = pkt->pts; | |
241 av_free_packet(pkt); | |
242 }while(pts < timestamp); | |
243 return 0; | |
244 } | |
245 | |
1324 | 246 AVInputFormat wv_demuxer = { |
247 "wv", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3286
diff
changeset
|
248 NULL_IF_CONFIG_SMALL("WavPack"), |
1324 | 249 sizeof(WVContext), |
250 wv_probe, | |
251 wv_read_header, | |
252 wv_read_packet, | |
3482 | 253 NULL, |
1743 | 254 wv_read_seek, |
1324 | 255 }; |