1/* 2 * WAV muxer and demuxer 3 * Copyright (c) 2001, 2002 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 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 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21#include "avformat.h" 22#include "raw.h" 23#include "riff.h" 24 25typedef struct { 26 int64_t data; 27 int64_t data_end; 28 int64_t minpts; 29 int64_t maxpts; 30 int last_duration; 31} WAVContext; 32 33#if CONFIG_WAV_MUXER 34static int wav_write_header(AVFormatContext *s) 35{ 36 WAVContext *wav = s->priv_data; 37 ByteIOContext *pb = s->pb; 38 int64_t fmt, fact; 39 40 put_tag(pb, "RIFF"); 41 put_le32(pb, 0); /* file length */ 42 put_tag(pb, "WAVE"); 43 44 /* format header */ 45 fmt = start_tag(pb, "fmt "); 46 if (put_wav_header(pb, s->streams[0]->codec) < 0) { 47 av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n", 48 s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE"); 49 av_free(wav); 50 return -1; 51 } 52 end_tag(pb, fmt); 53 54 if(s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */ 55 && !url_is_streamed(s->pb)) { 56 fact = start_tag(pb, "fact"); 57 put_le32(pb, 0); 58 end_tag(pb, fact); 59 } 60 61 av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate); 62 wav->maxpts = wav->last_duration = 0; 63 wav->minpts = INT64_MAX; 64 65 /* data header */ 66 wav->data = start_tag(pb, "data"); 67 68 put_flush_packet(pb); 69 70 return 0; 71} 72 73static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) 74{ 75 ByteIOContext *pb = s->pb; 76 WAVContext *wav = s->priv_data; 77 put_buffer(pb, pkt->data, pkt->size); 78 if(pkt->pts != AV_NOPTS_VALUE) { 79 wav->minpts = FFMIN(wav->minpts, pkt->pts); 80 wav->maxpts = FFMAX(wav->maxpts, pkt->pts); 81 wav->last_duration = pkt->duration; 82 } else 83 av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n"); 84 return 0; 85} 86 87static int wav_write_trailer(AVFormatContext *s) 88{ 89 ByteIOContext *pb = s->pb; 90 WAVContext *wav = s->priv_data; 91 int64_t file_size; 92 93 if (!url_is_streamed(s->pb)) { 94 end_tag(pb, wav->data); 95 96 /* update file size */ 97 file_size = url_ftell(pb); 98 url_fseek(pb, 4, SEEK_SET); 99 put_le32(pb, (uint32_t)(file_size - 8)); 100 url_fseek(pb, file_size, SEEK_SET); 101 102 put_flush_packet(pb); 103 104 if(s->streams[0]->codec->codec_tag != 0x01) { 105 /* Update num_samps in fact chunk */ 106 int number_of_samples; 107 number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration, 108 s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num, 109 s->streams[0]->time_base.den); 110 url_fseek(pb, wav->data-12, SEEK_SET); 111 put_le32(pb, number_of_samples); 112 url_fseek(pb, file_size, SEEK_SET); 113 put_flush_packet(pb); 114 } 115 } 116 return 0; 117} 118#endif /* CONFIG_WAV_MUXER */ 119 120/* return the size of the found tag */ 121/* XXX: > 2GB ? */ 122static int find_tag(ByteIOContext *pb, uint32_t tag1) 123{ 124 unsigned int tag; 125 int size; 126 127 for(;;) { 128 if (url_feof(pb)) 129 return -1; 130 tag = get_le32(pb); 131 size = get_le32(pb); 132 if (tag == tag1) 133 break; 134 url_fseek(pb, size, SEEK_CUR); 135 } 136 if (size < 0) 137 size = 0x7fffffff; 138 return size; 139} 140 141static int wav_probe(AVProbeData *p) 142{ 143 /* check file header */ 144 if (p->buf_size <= 32) 145 return 0; 146 if (p->buf[0] == 'R' && p->buf[1] == 'I' && 147 p->buf[2] == 'F' && p->buf[3] == 'F' && 148 p->buf[8] == 'W' && p->buf[9] == 'A' && 149 p->buf[10] == 'V' && p->buf[11] == 'E') 150 /* 151 Since ACT demuxer has standard WAV header at top of it's own, 152 returning score is decreased to avoid probe conflict 153 between ACT and WAV. 154 */ 155 return AVPROBE_SCORE_MAX - 1; 156 else 157 return 0; 158} 159 160/* wav input */ 161static int wav_read_header(AVFormatContext *s, 162 AVFormatParameters *ap) 163{ 164 int size; 165 unsigned int tag; 166 ByteIOContext *pb = s->pb; 167 AVStream *st; 168 WAVContext *wav = s->priv_data; 169 170 /* check RIFF header */ 171 tag = get_le32(pb); 172 173 if (tag != MKTAG('R', 'I', 'F', 'F')) 174 return -1; 175 get_le32(pb); /* file size */ 176 tag = get_le32(pb); 177 if (tag != MKTAG('W', 'A', 'V', 'E')) 178 return -1; 179 180 /* parse fmt header */ 181 size = find_tag(pb, MKTAG('f', 'm', 't', ' ')); 182 if (size < 0) 183 return -1; 184 st = av_new_stream(s, 0); 185 if (!st) 186 return AVERROR(ENOMEM); 187 188 get_wav_header(pb, st->codec, size); 189 st->need_parsing = AVSTREAM_PARSE_FULL; 190 191 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 192 193 size = find_tag(pb, MKTAG('d', 'a', 't', 'a')); 194 if (size < 0) 195 return -1; 196 wav->data_end= url_ftell(pb) + size; 197 return 0; 198} 199 200#define MAX_SIZE 4096 201 202static int wav_read_packet(AVFormatContext *s, 203 AVPacket *pkt) 204{ 205 int ret, size, left; 206 AVStream *st; 207 WAVContext *wav = s->priv_data; 208 209 if (url_feof(s->pb)) 210 return AVERROR(EIO); 211 st = s->streams[0]; 212 213 left= wav->data_end - url_ftell(s->pb); 214 if(left <= 0){ 215 left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); 216 if (left < 0) { 217 return AVERROR(EIO); 218 } 219 wav->data_end= url_ftell(s->pb) + left; 220 } 221 222 size = MAX_SIZE; 223 if (st->codec->block_align > 1) { 224 if (size < st->codec->block_align) 225 size = st->codec->block_align; 226 size = (size / st->codec->block_align) * st->codec->block_align; 227 } 228 size= FFMIN(size, left); 229 ret= av_get_packet(s->pb, pkt, size); 230 if (ret <= 0) 231 return AVERROR(EIO); 232 pkt->stream_index = 0; 233 234 /* note: we need to modify the packet size here to handle the last 235 packet */ 236 pkt->size = ret; 237 return ret; 238} 239 240static int wav_read_seek(AVFormatContext *s, 241 int stream_index, int64_t timestamp, int flags) 242{ 243 AVStream *st; 244 245 st = s->streams[0]; 246 switch(st->codec->codec_id) { 247 case CODEC_ID_MP2: 248 case CODEC_ID_MP3: 249 case CODEC_ID_AC3: 250 case CODEC_ID_DTS: 251 /* use generic seeking with dynamically generated indexes */ 252 return -1; 253 default: 254 break; 255 } 256 return pcm_read_seek(s, stream_index, timestamp, flags); 257} 258 259#if CONFIG_WAV_DEMUXER 260AVInputFormat wav_demuxer = { 261 "wav", 262 NULL_IF_CONFIG_SMALL("WAV format"), 263 sizeof(WAVContext), 264 wav_probe, 265 wav_read_header, 266 wav_read_packet, 267 NULL, 268 wav_read_seek, 269 .flags= AVFMT_GENERIC_INDEX, 270 .codec_tag= (const AVCodecTag* const []){codec_wav_tags, 0}, 271}; 272#endif 273#if CONFIG_WAV_MUXER 274AVOutputFormat wav_muxer = { 275 "wav", 276 NULL_IF_CONFIG_SMALL("WAV format"), 277 "audio/x-wav", 278 "wav", 279 sizeof(WAVContext), 280 CODEC_ID_PCM_S16LE, 281 CODEC_ID_NONE, 282 wav_write_header, 283 wav_write_packet, 284 wav_write_trailer, 285 .codec_tag= (const AVCodecTag* const []){codec_wav_tags, 0}, 286}; 287#endif 288