Libav 0.7.1
|
00001 /* 00002 * WAV muxer and demuxer 00003 * Copyright (c) 2001, 2002 Fabrice Bellard 00004 * 00005 * Sony Wave64 demuxer 00006 * RF64 demuxer 00007 * Copyright (c) 2009 Daniel Verkamp 00008 * 00009 * This file is part of Libav. 00010 * 00011 * Libav is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2.1 of the License, or (at your option) any later version. 00015 * 00016 * Libav is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with Libav; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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); /* file length */ 00048 ffio_wfourcc(pb, "WAVE"); 00049 00050 /* format header */ 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 return -1; 00056 } 00057 ff_end_tag(pb, fmt); 00058 00059 if (s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ 00060 && s->pb->seekable) { 00061 fact = ff_start_tag(pb, "fact"); 00062 avio_wl32(pb, 0); 00063 ff_end_tag(pb, fact); 00064 } 00065 00066 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); 00067 wav->maxpts = wav->last_duration = 0; 00068 wav->minpts = INT64_MAX; 00069 00070 /* data header */ 00071 wav->data = ff_start_tag(pb, "data"); 00072 00073 avio_flush(pb); 00074 00075 return 0; 00076 } 00077 00078 static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) 00079 { 00080 AVIOContext *pb = s->pb; 00081 WAVContext *wav = s->priv_data; 00082 avio_write(pb, pkt->data, pkt->size); 00083 if(pkt->pts != AV_NOPTS_VALUE) { 00084 wav->minpts = FFMIN(wav->minpts, pkt->pts); 00085 wav->maxpts = FFMAX(wav->maxpts, pkt->pts); 00086 wav->last_duration = pkt->duration; 00087 } else 00088 av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n"); 00089 return 0; 00090 } 00091 00092 static int wav_write_trailer(AVFormatContext *s) 00093 { 00094 AVIOContext *pb = s->pb; 00095 WAVContext *wav = s->priv_data; 00096 int64_t file_size; 00097 00098 avio_flush(pb); 00099 00100 if (s->pb->seekable) { 00101 ff_end_tag(pb, wav->data); 00102 00103 /* update file size */ 00104 file_size = avio_tell(pb); 00105 avio_seek(pb, 4, SEEK_SET); 00106 avio_wl32(pb, (uint32_t)(file_size - 8)); 00107 avio_seek(pb, file_size, SEEK_SET); 00108 00109 avio_flush(pb); 00110 00111 if(s->streams[0]->codec->codec_tag != 0x01) { 00112 /* Update num_samps in fact chunk */ 00113 int number_of_samples; 00114 number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration, 00115 s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num, 00116 s->streams[0]->time_base.den); 00117 avio_seek(pb, wav->data-12, SEEK_SET); 00118 avio_wl32(pb, number_of_samples); 00119 avio_seek(pb, file_size, SEEK_SET); 00120 avio_flush(pb); 00121 } 00122 } 00123 return 0; 00124 } 00125 00126 AVOutputFormat ff_wav_muxer = { 00127 "wav", 00128 NULL_IF_CONFIG_SMALL("WAV format"), 00129 "audio/x-wav", 00130 "wav", 00131 sizeof(WAVContext), 00132 CODEC_ID_PCM_S16LE, 00133 CODEC_ID_NONE, 00134 wav_write_header, 00135 wav_write_packet, 00136 wav_write_trailer, 00137 .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0}, 00138 }; 00139 #endif /* CONFIG_WAV_MUXER */ 00140 00141 00142 #if CONFIG_WAV_DEMUXER 00143 00144 static int64_t next_tag(AVIOContext *pb, unsigned int *tag) 00145 { 00146 *tag = avio_rl32(pb); 00147 return avio_rl32(pb); 00148 } 00149 00150 /* return the size of the found tag */ 00151 static int64_t find_tag(AVIOContext *pb, uint32_t tag1) 00152 { 00153 unsigned int tag; 00154 int64_t size; 00155 00156 for (;;) { 00157 if (pb->eof_reached) 00158 return -1; 00159 size = next_tag(pb, &tag); 00160 if (tag == tag1) 00161 break; 00162 avio_skip(pb, size); 00163 } 00164 return size; 00165 } 00166 00167 static int wav_probe(AVProbeData *p) 00168 { 00169 /* check file header */ 00170 if (p->buf_size <= 32) 00171 return 0; 00172 if (!memcmp(p->buf + 8, "WAVE", 4)) { 00173 if (!memcmp(p->buf, "RIFF", 4)) 00174 /* 00175 Since ACT demuxer has standard WAV header at top of it's own, 00176 returning score is decreased to avoid probe conflict 00177 between ACT and WAV. 00178 */ 00179 return AVPROBE_SCORE_MAX - 1; 00180 else if (!memcmp(p->buf, "RF64", 4) && 00181 !memcmp(p->buf + 12, "ds64", 4)) 00182 return AVPROBE_SCORE_MAX; 00183 } 00184 return 0; 00185 } 00186 00187 /* wav input */ 00188 static int wav_read_header(AVFormatContext *s, 00189 AVFormatParameters *ap) 00190 { 00191 int64_t size, av_uninit(data_size); 00192 int64_t sample_count=0; 00193 int rf64; 00194 unsigned int tag; 00195 AVIOContext *pb = s->pb; 00196 AVStream *st; 00197 WAVContext *wav = s->priv_data; 00198 int ret; 00199 00200 /* check RIFF header */ 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); /* file size */ 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); /* RIFF size */ 00218 data_size = avio_rl64(pb); 00219 sample_count = avio_rl64(pb); 00220 avio_skip(pb, size - 16); /* skip rest of ds64 chunk */ 00221 } 00222 00223 /* parse fmt header */ 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 ret = ff_get_wav_header(pb, st->codec, size); 00232 if (ret < 0) 00233 return ret; 00234 st->need_parsing = AVSTREAM_PARSE_FULL; 00235 00236 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00237 00238 for (;;) { 00239 if (pb->eof_reached) 00240 return -1; 00241 size = next_tag(pb, &tag); 00242 if (tag == MKTAG('d', 'a', 't', 'a')){ 00243 break; 00244 }else if (tag == MKTAG('f','a','c','t') && !sample_count){ 00245 sample_count = avio_rl32(pb); 00246 size -= 4; 00247 } 00248 avio_skip(pb, size); 00249 } 00250 if (rf64) 00251 size = data_size; 00252 if (size < 0) 00253 return -1; 00254 if (!size) { 00255 wav->data_end = INT64_MAX; 00256 } else 00257 wav->data_end= avio_tell(pb) + size; 00258 00259 if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id)) 00260 sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); 00261 if (sample_count) 00262 st->duration = sample_count; 00263 return 0; 00264 } 00265 00269 static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16]) 00270 { 00271 uint8_t guid[16]; 00272 int64_t size; 00273 00274 while (!pb->eof_reached) { 00275 avio_read(pb, guid, 16); 00276 size = avio_rl64(pb); 00277 if (size <= 24) 00278 return -1; 00279 if (!memcmp(guid, guid1, 16)) 00280 return size; 00281 avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24); 00282 } 00283 return -1; 00284 } 00285 00286 static const uint8_t guid_data[16] = { 'd', 'a', 't', 'a', 00287 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; 00288 00289 #define MAX_SIZE 4096 00290 00291 static int wav_read_packet(AVFormatContext *s, 00292 AVPacket *pkt) 00293 { 00294 int ret, size; 00295 int64_t left; 00296 AVStream *st; 00297 WAVContext *wav = s->priv_data; 00298 00299 st = s->streams[0]; 00300 00301 left = wav->data_end - avio_tell(s->pb); 00302 if (left <= 0){ 00303 if (CONFIG_W64_DEMUXER && wav->w64) 00304 left = find_guid(s->pb, guid_data) - 24; 00305 else 00306 left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); 00307 if (left < 0) 00308 return AVERROR_EOF; 00309 wav->data_end= avio_tell(s->pb) + left; 00310 } 00311 00312 size = MAX_SIZE; 00313 if (st->codec->block_align > 1) { 00314 if (size < st->codec->block_align) 00315 size = st->codec->block_align; 00316 size = (size / st->codec->block_align) * st->codec->block_align; 00317 } 00318 size = FFMIN(size, left); 00319 ret = av_get_packet(s->pb, pkt, size); 00320 if (ret < 0) 00321 return ret; 00322 pkt->stream_index = 0; 00323 00324 return ret; 00325 } 00326 00327 static int wav_read_seek(AVFormatContext *s, 00328 int stream_index, int64_t timestamp, int flags) 00329 { 00330 AVStream *st; 00331 00332 st = s->streams[0]; 00333 switch (st->codec->codec_id) { 00334 case CODEC_ID_MP2: 00335 case CODEC_ID_MP3: 00336 case CODEC_ID_AC3: 00337 case CODEC_ID_DTS: 00338 /* use generic seeking with dynamically generated indexes */ 00339 return -1; 00340 default: 00341 break; 00342 } 00343 return pcm_read_seek(s, stream_index, timestamp, flags); 00344 } 00345 00346 AVInputFormat ff_wav_demuxer = { 00347 "wav", 00348 NULL_IF_CONFIG_SMALL("WAV format"), 00349 sizeof(WAVContext), 00350 wav_probe, 00351 wav_read_header, 00352 wav_read_packet, 00353 NULL, 00354 wav_read_seek, 00355 .flags= AVFMT_GENERIC_INDEX, 00356 .codec_tag= (const AVCodecTag* const []){ff_codec_wav_tags, 0}, 00357 }; 00358 #endif /* CONFIG_WAV_DEMUXER */ 00359 00360 00361 #if CONFIG_W64_DEMUXER 00362 static const uint8_t guid_riff[16] = { 'r', 'i', 'f', 'f', 00363 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }; 00364 00365 static const uint8_t guid_wave[16] = { 'w', 'a', 'v', 'e', 00366 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; 00367 00368 static const uint8_t guid_fmt [16] = { 'f', 'm', 't', ' ', 00369 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; 00370 00371 static int w64_probe(AVProbeData *p) 00372 { 00373 if (p->buf_size <= 40) 00374 return 0; 00375 if (!memcmp(p->buf, guid_riff, 16) && 00376 !memcmp(p->buf + 24, guid_wave, 16)) 00377 return AVPROBE_SCORE_MAX; 00378 else 00379 return 0; 00380 } 00381 00382 static int w64_read_header(AVFormatContext *s, AVFormatParameters *ap) 00383 { 00384 int64_t size; 00385 AVIOContext *pb = s->pb; 00386 WAVContext *wav = s->priv_data; 00387 AVStream *st; 00388 uint8_t guid[16]; 00389 int ret; 00390 00391 avio_read(pb, guid, 16); 00392 if (memcmp(guid, guid_riff, 16)) 00393 return -1; 00394 00395 if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */ 00396 return -1; 00397 00398 avio_read(pb, guid, 16); 00399 if (memcmp(guid, guid_wave, 16)) { 00400 av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); 00401 return -1; 00402 } 00403 00404 size = find_guid(pb, guid_fmt); 00405 if (size < 0) { 00406 av_log(s, AV_LOG_ERROR, "could not find fmt guid\n"); 00407 return -1; 00408 } 00409 00410 st = av_new_stream(s, 0); 00411 if (!st) 00412 return AVERROR(ENOMEM); 00413 00414 /* subtract chunk header size - normal wav file doesn't count it */ 00415 ret = ff_get_wav_header(pb, st->codec, size - 24); 00416 if (ret < 0) 00417 return ret; 00418 avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); 00419 00420 st->need_parsing = AVSTREAM_PARSE_FULL; 00421 00422 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 00423 00424 size = find_guid(pb, guid_data); 00425 if (size < 0) { 00426 av_log(s, AV_LOG_ERROR, "could not find data guid\n"); 00427 return -1; 00428 } 00429 wav->data_end = avio_tell(pb) + size - 24; 00430 wav->w64 = 1; 00431 00432 return 0; 00433 } 00434 00435 AVInputFormat ff_w64_demuxer = { 00436 "w64", 00437 NULL_IF_CONFIG_SMALL("Sony Wave64 format"), 00438 sizeof(WAVContext), 00439 w64_probe, 00440 w64_read_header, 00441 wav_read_packet, 00442 NULL, 00443 wav_read_seek, 00444 .flags = AVFMT_GENERIC_INDEX, 00445 .codec_tag = (const AVCodecTag* const []){ff_codec_wav_tags, 0}, 00446 }; 00447 #endif /* CONFIG_W64_DEMUXER */