• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/wav.c

Go to the documentation of this file.
00001 /*
00002  * WAV muxer and demuxer
00003  * Copyright (c) 2001, 2002 Fabrice Bellard
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 #include "avformat.h"
00022 #include "raw.h"
00023 #include "riff.h"
00024 
00025 typedef struct {
00026     int64_t data;
00027     int64_t data_end;
00028     int64_t minpts;
00029     int64_t maxpts;
00030     int last_duration;
00031 } WAVContext;
00032 
00033 #if CONFIG_WAV_MUXER
00034 static int wav_write_header(AVFormatContext *s)
00035 {
00036     WAVContext *wav = s->priv_data;
00037     ByteIOContext *pb = s->pb;
00038     int64_t fmt, fact;
00039 
00040     put_tag(pb, "RIFF");
00041     put_le32(pb, 0); /* file length */
00042     put_tag(pb, "WAVE");
00043 
00044     /* format header */
00045     fmt = start_tag(pb, "fmt ");
00046     if (put_wav_header(pb, s->streams[0]->codec) < 0) {
00047         av_log(s, AV_LOG_ERROR, "%s codec not supported in WAVE format\n",
00048                s->streams[0]->codec->codec ? s->streams[0]->codec->codec->name : "NONE");
00049         av_free(wav);
00050         return -1;
00051     }
00052     end_tag(pb, fmt);
00053 
00054     if(s->streams[0]->codec->codec_tag != 0x01 /* hence for all other than PCM */
00055        && !url_is_streamed(s->pb)) {
00056         fact = start_tag(pb, "fact");
00057         put_le32(pb, 0);
00058         end_tag(pb, fact);
00059     }
00060 
00061     av_set_pts_info(s->streams[0], 64, 1, s->streams[0]->codec->sample_rate);
00062     wav->maxpts = wav->last_duration = 0;
00063     wav->minpts = INT64_MAX;
00064 
00065     /* data header */
00066     wav->data = start_tag(pb, "data");
00067 
00068     put_flush_packet(pb);
00069 
00070     return 0;
00071 }
00072 
00073 static int wav_write_packet(AVFormatContext *s, AVPacket *pkt)
00074 {
00075     ByteIOContext *pb = s->pb;
00076     WAVContext *wav = s->priv_data;
00077     put_buffer(pb, pkt->data, pkt->size);
00078     if(pkt->pts != AV_NOPTS_VALUE) {
00079         wav->minpts = FFMIN(wav->minpts, pkt->pts);
00080         wav->maxpts = FFMAX(wav->maxpts, pkt->pts);
00081         wav->last_duration = pkt->duration;
00082     } else
00083         av_log(s, AV_LOG_ERROR, "wav_write_packet: NOPTS\n");
00084     return 0;
00085 }
00086 
00087 static int wav_write_trailer(AVFormatContext *s)
00088 {
00089     ByteIOContext *pb = s->pb;
00090     WAVContext *wav = s->priv_data;
00091     int64_t file_size;
00092 
00093     if (!url_is_streamed(s->pb)) {
00094         end_tag(pb, wav->data);
00095 
00096         /* update file size */
00097         file_size = url_ftell(pb);
00098         url_fseek(pb, 4, SEEK_SET);
00099         put_le32(pb, (uint32_t)(file_size - 8));
00100         url_fseek(pb, file_size, SEEK_SET);
00101 
00102         put_flush_packet(pb);
00103 
00104         if(s->streams[0]->codec->codec_tag != 0x01) {
00105             /* Update num_samps in fact chunk */
00106             int number_of_samples;
00107             number_of_samples = av_rescale(wav->maxpts - wav->minpts + wav->last_duration,
00108                                            s->streams[0]->codec->sample_rate * (int64_t)s->streams[0]->time_base.num,
00109                                            s->streams[0]->time_base.den);
00110             url_fseek(pb, wav->data-12, SEEK_SET);
00111             put_le32(pb, number_of_samples);
00112             url_fseek(pb, file_size, SEEK_SET);
00113             put_flush_packet(pb);
00114         }
00115     }
00116     return 0;
00117 }
00118 #endif /* CONFIG_WAV_MUXER */
00119 
00120 /* return the size of the found tag */
00121 /* XXX: > 2GB ? */
00122 static int find_tag(ByteIOContext *pb, uint32_t tag1)
00123 {
00124     unsigned int tag;
00125     int size;
00126 
00127     for(;;) {
00128         if (url_feof(pb))
00129             return -1;
00130         tag = get_le32(pb);
00131         size = get_le32(pb);
00132         if (tag == tag1)
00133             break;
00134         url_fseek(pb, size, SEEK_CUR);
00135     }
00136     if (size < 0)
00137         size = 0x7fffffff;
00138     return size;
00139 }
00140 
00141 static int wav_probe(AVProbeData *p)
00142 {
00143     /* check file header */
00144     if (p->buf_size <= 32)
00145         return 0;
00146     if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
00147         p->buf[2] == 'F' && p->buf[3] == 'F' &&
00148         p->buf[8] == 'W' && p->buf[9] == 'A' &&
00149         p->buf[10] == 'V' && p->buf[11] == 'E')
00150         /*
00151           Since ACT demuxer has standard WAV header at top of it's own,
00152           returning score is decreased to avoid probe conflict
00153           between ACT and WAV.
00154         */
00155         return AVPROBE_SCORE_MAX - 1;
00156     else
00157         return 0;
00158 }
00159 
00160 /* wav input */
00161 static int wav_read_header(AVFormatContext *s,
00162                            AVFormatParameters *ap)
00163 {
00164     int size;
00165     unsigned int tag;
00166     ByteIOContext *pb = s->pb;
00167     AVStream *st;
00168     WAVContext *wav = s->priv_data;
00169 
00170     /* check RIFF header */
00171     tag = get_le32(pb);
00172 
00173     if (tag != MKTAG('R', 'I', 'F', 'F'))
00174         return -1;
00175     get_le32(pb); /* file size */
00176     tag = get_le32(pb);
00177     if (tag != MKTAG('W', 'A', 'V', 'E'))
00178         return -1;
00179 
00180     /* parse fmt header */
00181     size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
00182     if (size < 0)
00183         return -1;
00184     st = av_new_stream(s, 0);
00185     if (!st)
00186         return AVERROR(ENOMEM);
00187 
00188     get_wav_header(pb, st->codec, size);
00189     st->need_parsing = AVSTREAM_PARSE_FULL;
00190 
00191     av_set_pts_info(st, 64, 1, st->codec->sample_rate);
00192 
00193     size = find_tag(pb, MKTAG('d', 'a', 't', 'a'));
00194     if (size < 0)
00195         return -1;
00196     wav->data_end= url_ftell(pb) + size;
00197     return 0;
00198 }
00199 
00200 #define MAX_SIZE 4096
00201 
00202 static int wav_read_packet(AVFormatContext *s,
00203                            AVPacket *pkt)
00204 {
00205     int ret, size, left;
00206     AVStream *st;
00207     WAVContext *wav = s->priv_data;
00208 
00209     if (url_feof(s->pb))
00210         return AVERROR(EIO);
00211     st = s->streams[0];
00212 
00213     left= wav->data_end - url_ftell(s->pb);
00214     if(left <= 0){
00215         left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a'));
00216         if (left < 0) {
00217             return AVERROR(EIO);
00218         }
00219         wav->data_end= url_ftell(s->pb) + left;
00220     }
00221 
00222     size = MAX_SIZE;
00223     if (st->codec->block_align > 1) {
00224         if (size < st->codec->block_align)
00225             size = st->codec->block_align;
00226         size = (size / st->codec->block_align) * st->codec->block_align;
00227     }
00228     size= FFMIN(size, left);
00229     ret= av_get_packet(s->pb, pkt, size);
00230     if (ret <= 0)
00231         return AVERROR(EIO);
00232     pkt->stream_index = 0;
00233 
00234     /* note: we need to modify the packet size here to handle the last
00235        packet */
00236     pkt->size = ret;
00237     return ret;
00238 }
00239 
00240 static int wav_read_seek(AVFormatContext *s,
00241                          int stream_index, int64_t timestamp, int flags)
00242 {
00243     AVStream *st;
00244 
00245     st = s->streams[0];
00246     switch(st->codec->codec_id) {
00247     case CODEC_ID_MP2:
00248     case CODEC_ID_MP3:
00249     case CODEC_ID_AC3:
00250     case CODEC_ID_DTS:
00251         /* use generic seeking with dynamically generated indexes */
00252         return -1;
00253     default:
00254         break;
00255     }
00256     return pcm_read_seek(s, stream_index, timestamp, flags);
00257 }
00258 
00259 #if CONFIG_WAV_DEMUXER
00260 AVInputFormat wav_demuxer = {
00261     "wav",
00262     NULL_IF_CONFIG_SMALL("WAV format"),
00263     sizeof(WAVContext),
00264     wav_probe,
00265     wav_read_header,
00266     wav_read_packet,
00267     NULL,
00268     wav_read_seek,
00269     .flags= AVFMT_GENERIC_INDEX,
00270     .codec_tag= (const AVCodecTag* const []){codec_wav_tags, 0},
00271 };
00272 #endif
00273 #if CONFIG_WAV_MUXER
00274 AVOutputFormat wav_muxer = {
00275     "wav",
00276     NULL_IF_CONFIG_SMALL("WAV format"),
00277     "audio/x-wav",
00278     "wav",
00279     sizeof(WAVContext),
00280     CODEC_ID_PCM_S16LE,
00281     CODEC_ID_NONE,
00282     wav_write_header,
00283     wav_write_packet,
00284     wav_write_trailer,
00285     .codec_tag= (const AVCodecTag* const []){codec_wav_tags, 0},
00286 };
00287 #endif

Generated on Tue Nov 4 2014 12:59:24 for ffmpeg by  doxygen 1.7.1