00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "avformat.h"
00026 #include "avio_internal.h"
00027 #include "pcm.h"
00028 #include "riff.h"
00029
00030 typedef struct {
00031 int64_t data;
00032 int64_t data_end;
00033 int64_t minpts;
00034 int64_t maxpts;
00035 int last_duration;
00036 int w64;
00037 } WAVContext;
00038
00039 #if CONFIG_WAV_MUXER
00040 static int wav_write_header(AVFormatContext *s)
00041 {
00042 WAVContext *wav = s->priv_data;
00043 AVIOContext *pb = s->pb;
00044 int64_t fmt, fact;
00045
00046 ffio_wfourcc(pb, "RIFF");
00047 avio_wl32(pb, 0);
00048 ffio_wfourcc(pb, "WAVE");
00049
00050
00051 fmt = ff_start_tag(pb, "fmt ");
00052 if (ff_put_wav_header(pb, s->streams[0]->codec) < 0) {
00053 av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
00054 s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
00055 av_free(wav);
00056 return -1;
00057 }
00058 ff_end_tag(pb, fmt);
00059
00060 if (s->streams[0]->codec->codec_tag != 0x01
00061 && !url_is_streamed(s->pb)) {
00062 fact = ff_start_tag(pb, "fact");
00063 avio_wl32(pb, 0);
00064 ff_end_tag(pb, fact);
00065 }
00066
00067 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
00068 wav->maxpts = wav->last_duration = 0;
00069 wav->minpts = INT64_MAX;
00070
00071
00072 wav->data = ff_start_tag(pb, "data");
00073
00074 put_flush_packet(pb);
00075
00076 return 0;
00077 }
00078
00079 static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
00080 {
00081 AVIOContext *pb = s->pb;
00082 WAVContext *wav = s->priv_data;
00083 avio_write(pb, pkt->data, pkt->size);
00084 if(pkt->pts != AV_NOPTS_VALUE) {
00085 wav->minpts = FFMIN(wav->minpts, pkt->pts);
00086 wav->maxpts = FFMAX(wav->maxpts, pkt->pts);
00087 wav->last_duration = pkt->duration;
00088 } else
00089 av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n");
00090 return 0;
00091 }
00092
00093 static int wav_write_trailer(AVFormatContext *s)
00094 {
00095 AVIOContext *pb = s->pb;
00096 WAVContext *wav = s->priv_data;
00097 int64_t file_size;
00098
00099 put_flush_packet(pb);
00100
00101 if (!url_is_streamed(s->pb)) {
00102 ff_end_tag(pb, wav->data);
00103
00104
00105 file_size = avio_tell(pb);
00106 avio_seek(pb, 4, SEEK_SET);
00107 avio_wl32(pb, (uint32_t)(file_size - 8));
00108 avio_seek(pb, file_size, SEEK_SET);
00109
00110 put_flush_packet(pb);
00111
00112 if(s->streams[0]->codec->codec_tag != 0x01) {
00113
00114 int number_of_samples;
00115 number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
00116 s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
00117 s->streams[0]->time_base.den);
00118 avio_seek(pb, wav->data-12, SEEK_SET);
00119 avio_wl32(pb, number_of_samples);
00120 avio_seek(pb, file_size, SEEK_SET);
00121 put_flush_packet(pb);
00122 }
00123 }
00124 return 0;
00125 }
00126
00127 AVOutputFormat ff_wav_muxer = {
00128 "wav",
00129 NULL_IF_CONFIG_SMALL("WAV format"),
00130 "audio/x-wav",
00131 "wav",
00132 sizeof(WAVContext),
00133 CODEC_ID_PCM_S16LE,
00134 CODEC_ID_NONE,
00135 wav_write_header,
00136 wav_write_packet,
00137 wav_write_trailer,
00138 .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
00139 };
00140 #endif
00141
00142
00143 #if CONFIG_WAV_DEMUXER
00144
00145 static int64_t next_tag(AVIOContext *pb, unsigned int *tag)
00146 {
00147 *tag = avio_rl32(pb);
00148 return avio_rl32(pb);
00149 }
00150
00151
00152 static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
00153 {
00154 unsigned int tag;
00155 int64_t size;
00156
00157 for (;;) {
00158 if (url_feof(pb))
00159 return -1;
00160 size = next_tag(pb, &tag);
00161 if (tag == tag1)
00162 break;
00163 avio_seek(pb, size, SEEK_CUR);
00164 }
00165 return size;
00166 }
00167
00168 static int wav_probe(AVProbeData *p)
00169 {
00170
00171 if (p->buf_size <= 32)
00172 return 0;
00173 if (!memcmp(p->buf + 8, "WAVE", 4)) {
00174 if (!memcmp(p->buf, "RIFF", 4))
00175
00176
00177
00178
00179
00180 return AVPROBE_SCORE_MAX - 1;
00181 else if (!memcmp(p->buf, "RF64", 4) &&
00182 !memcmp(p->buf + 12, "ds64", 4))
00183 return AVPROBE_SCORE_MAX;
00184 }
00185 return 0;
00186 }
00187
00188
00189 static int wav_read_header(AVFormatContext *s,
00190 AVFormatParameters *ap)
00191 {
00192 int64_t size, av_uninit(data_size);
00193 int64_t sample_count=0;
00194 int rf64;
00195 unsigned int tag;
00196 AVIOContext *pb = s->pb;
00197 AVStream *st;
00198 WAVContext *wav = s->priv_data;
00199
00200
00201 tag = avio_rl32(pb);
00202
00203 rf64 = tag == MKTAG('R', 'F', '6', '4');
00204 if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
00205 return -1;
00206 avio_rl32(pb);
00207 tag = avio_rl32(pb);
00208 if (tag != MKTAG('W', 'A', 'V', 'E'))
00209 return -1;
00210
00211 if (rf64) {
00212 if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
00213 return -1;
00214 size = avio_rl32(pb);
00215 if (size < 16)
00216 return -1;
00217 avio_rl64(pb);
00218 data_size = avio_rl64(pb);
00219 sample_count = avio_rl64(pb);
00220 avio_seek(pb, size - 16, SEEK_CUR);
00221 }
00222
00223
00224 size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
00225 if (size < 0)
00226 return -1;
00227 st = av_new_stream(s, 0);
00228 if (!st)
00229 return AVERROR(ENOMEM);
00230
00231 ff_get_wav_header(pb, st->codec, size);
00232 st->need_parsing = AVSTREAM_PARSE_FULL;
00233
00234 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00235
00236 for (;;) {
00237 if (url_feof(pb))
00238 return -1;
00239 size = next_tag(pb, &tag);
00240 if (tag == MKTAG('d', 'a', 't', 'a')){
00241 break;
00242 }else if (tag == MKTAG('f','a','c','t') && !sample_count){
00243 sample_count = avio_rl32(pb);
00244 size -= 4;
00245 }
00246 avio_seek(pb, size, SEEK_CUR);
00247 }
00248 if (rf64)
00249 size = data_size;
00250 if (size < 0)
00251 return -1;
00252 if (!size) {
00253 wav->data_end = INT64_MAX;
00254 } else
00255 wav->data_end= avio_tell(pb) + size;
00256
00257 if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
00258 sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
00259 if (sample_count)
00260 st->duration = sample_count;
00261 return 0;
00262 }
00263
00267 static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16])
00268 {
00269 uint8_t guid[16];
00270 int64_t size;
00271
00272 while (!url_feof(pb)) {
00273 avio_read(pb, guid, 16);
00274 size = avio_rl64(pb);
00275 if (size <= 24)
00276 return -1;
00277 if (!memcmp(guid, guid1, 16))
00278 return size;
00279 avio_seek(pb, FFALIGN(size, INT64_C(8)) - 24, SEEK_CUR);
00280 }
00281 return -1;
00282 }
00283
00284 static const uint8_t guid_data[16] = { 'd', 'a', 't', 'a',
00285 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };
00286
00287 #define MAX_SIZE 4096
00288
00289 static int wav_read_packet(AVFormatContext *s,
00290 AVPacket *pkt)
00291 {
00292 int ret, size;
00293 int64_t left;
00294 AVStream *st;
00295 WAVContext *wav = s->priv_data;
00296
00297 st = s->streams[0];
00298
00299 left = wav->data_end - avio_tell(s->pb);
00300 if (left <= 0){
00301 if (CONFIG_W64_DEMUXER && wav->w64)
00302 left = find_guid(s->pb, guid_data) - 24;
00303 else
00304 left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
00305 if (left < 0)
00306 return AVERROR_EOF;
00307 wav->data_end= avio_tell(s->pb) + left;
00308 }
00309
00310 size = MAX_SIZE;
00311 if (st->codec->block_align > 1) {
00312 if (size < st->codec->block_align)
00313 size = st->codec->block_align;
00314 size = (size / st->codec->block_align) * st->codec->block_align;
00315 }
00316 size = FFMIN(size, left);
00317 ret = av_get_packet(s->pb, pkt, size);
00318 if (ret < 0)
00319 return ret;
00320 pkt->stream_index = 0;
00321
00322 return ret;
00323 }
00324
00325 static int wav_read_seek(AVFormatContext *s,
00326 int stream_index, int64_t timestamp, int flags)
00327 {
00328 AVStream *st;
00329
00330 st = s->streams[0];
00331 switch (st->codec->codec_id) {
00332 case CODEC_ID_MP2:
00333 case CODEC_ID_MP3:
00334 case CODEC_ID_AC3:
00335 case CODEC_ID_DTS:
00336
00337 return -1;
00338 default:
00339 break;
00340 }
00341 return pcm_read_seek(s, stream_index, timestamp, flags);
00342 }
00343
00344 AVInputFormat ff_wav_demuxer = {
00345 "wav",
00346 NULL_IF_CONFIG_SMALL("WAV format"),
00347 sizeof(WAVContext),
00348 wav_probe,
00349 wav_read_header,
00350 wav_read_packet,
00351 NULL,
00352 wav_read_seek,
00353 .flags= AVFMT_GENERIC_INDEX,
00354 .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0},
00355 };
00356 #endif
00357
00358
00359 #if CONFIG_W64_DEMUXER
00360 static const uint8_t guid_riff[16] = { 'r', 'i', 'f', 'f',
00361 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 };
00362
00363 static const uint8_t guid_wave[16] = { 'w', 'a', 'v', 'e',
00364 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };
00365
00366 static const uint8_t guid_fmt [16] = { 'f', 'm', 't', ' ',
00367 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A };
00368
00369 static int w64_probe(AVProbeData *p)
00370 {
00371 if (p->buf_size <= 40)
00372 return 0;
00373 if (!memcmp(p->buf, guid_riff, 16) &&
00374 !memcmp(p->buf + 24, guid_wave, 16))
00375 return AVPROBE_SCORE_MAX;
00376 else
00377 return 0;
00378 }
00379
00380 static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap)
00381 {
00382 int64_t size;
00383 AVIOContext *pb = s->pb;
00384 WAVContext *wav = s->priv_data;
00385 AVStream *st;
00386 uint8_t guid[16];
00387
00388 avio_read(pb, guid, 16);
00389 if (memcmp(guid, guid_riff, 16))
00390 return -1;
00391
00392 if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8)
00393 return -1;
00394
00395 avio_read(pb, guid, 16);
00396 if (memcmp(guid, guid_wave, 16)) {
00397 av_log(s, AV_LOG_ERROR, "could not find wave guid\n");
00398 return -1;
00399 }
00400
00401 size = find_guid(pb, guid_fmt);
00402 if (size < 0) {
00403 av_log(s, AV_LOG_ERROR, "could not find fmt guid\n");
00404 return -1;
00405 }
00406
00407 st = av_new_stream(s, 0);
00408 if (!st)
00409 return AVERROR(ENOMEM);
00410
00411
00412 ff_get_wav_header(pb, st->codec, size - 24);
00413 avio_seek(pb, FFALIGN(size, INT64_C(8)) - size, SEEK_CUR);
00414
00415 st->need_parsing = AVSTREAM_PARSE_FULL;
00416
00417 av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00418
00419 size = find_guid(pb, guid_data);
00420 if (size < 0) {
00421 av_log(s, AV_LOG_ERROR, "could not find data guid\n");
00422 return -1;
00423 }
00424 wav->data_end = avio_tell(pb) + size - 24;
00425 wav->w64 = 1;
00426
00427 return 0;
00428 }
00429
00430 AVInputFormat ff_w64_demuxer = {
00431 "w64",
00432 NULL_IF_CONFIG_SMALL("Sony Wave64 format"),
00433 sizeof(WAVContext),
00434 w64_probe,
00435 w64_read_header,
00436 wav_read_packet,
00437 NULL,
00438 wav_read_seek,
00439 .flags = AVFMT_GENERIC_INDEX,
00440 .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0},
00441 };
00442 #endif