3 * Copyright (c) 2001, 2002 Fabrice Bellard
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "libavutil/dict.h"
26 #include "libavutil/common.h"
27 #include "libavutil/mathematics.h"
28 #include "libavutil/opt.h"
32 #include "avio_internal.h"
36 typedef struct WAVMuxContext
{
46 static inline void bwf_write_bext_string(AVFormatContext
*s
, const char *key
, int maxlen
)
48 AVDictionaryEntry
*tag
;
51 if (tag
= av_dict_get(s
->metadata
, key
, NULL
, 0)) {
52 len
= strlen(tag
->value
);
53 len
= FFMIN(len
, maxlen
);
54 avio_write(s
->pb
, tag
->value
, len
);
57 ffio_fill(s
->pb
, 0, maxlen
- len
);
60 static void bwf_write_bext_chunk(AVFormatContext
*s
)
62 AVDictionaryEntry
*tmp_tag
;
63 uint64_t time_reference
= 0;
64 int64_t bext
= ff_start_tag(s
->pb
, "bext");
66 bwf_write_bext_string(s
, "description", 256);
67 bwf_write_bext_string(s
, "originator", 32);
68 bwf_write_bext_string(s
, "originator_reference", 32);
69 bwf_write_bext_string(s
, "origination_date", 10);
70 bwf_write_bext_string(s
, "origination_time", 8);
72 if (tmp_tag
= av_dict_get(s
->metadata
, "time_reference", NULL
, 0))
73 time_reference
= strtoll(tmp_tag
->value
, NULL
, 10);
74 avio_wl64(s
->pb
, time_reference
);
75 avio_wl16(s
->pb
, 1); // set version to 1
77 if (tmp_tag
= av_dict_get(s
->metadata
, "umid", NULL
, 0)) {
78 unsigned char umidpart_str
[17] = {0};
81 int len
= strlen(tmp_tag
->value
+2);
83 for (i
= 0; i
< len
/16; i
++) {
84 memcpy(umidpart_str
, tmp_tag
->value
+ 2 + (i
*16), 16);
85 umidpart
= strtoll(umidpart_str
, NULL
, 16);
86 avio_wb64(s
->pb
, umidpart
);
88 ffio_fill(s
->pb
, 0, 64 - i
*8);
90 ffio_fill(s
->pb
, 0, 64); // zero UMID
92 ffio_fill(s
->pb
, 0, 190); // Reserved
94 if (tmp_tag
= av_dict_get(s
->metadata
, "coding_history", NULL
, 0))
95 avio_put_str(s
->pb
, tmp_tag
->value
);
97 ff_end_tag(s
->pb
, bext
);
100 static int wav_write_header(AVFormatContext
*s
)
102 WAVMuxContext
*wav
= s
->priv_data
;
103 AVIOContext
*pb
= s
->pb
;
106 ffio_wfourcc(pb
, "RIFF");
107 avio_wl32(pb
, 0); /* file length */
108 ffio_wfourcc(pb
, "WAVE");
111 fmt
= ff_start_tag(pb
, "fmt ");
112 if (ff_put_wav_header(pb
, s
->streams
[0]->codec
) < 0) {
113 av_log(s
, AV_LOG_ERROR
, "%s codec not supported in WAVE format\n",
114 s
->streams
[0]->codec
->codec
? s
->streams
[0]->codec
->codec
->name
: "NONE");
119 if (s
->streams
[0]->codec
->codec_tag
!= 0x01 /* hence for all other than PCM */
120 && s
->pb
->seekable
) {
121 wav
->fact_pos
= ff_start_tag(pb
, "fact");
123 ff_end_tag(pb
, wav
->fact_pos
);
127 bwf_write_bext_chunk(s
);
129 avpriv_set_pts_info(s
->streams
[0], 64, 1, s
->streams
[0]->codec
->sample_rate
);
130 wav
->maxpts
= wav
->last_duration
= 0;
131 wav
->minpts
= INT64_MAX
;
134 ff_riff_write_info(s
);
137 wav
->data
= ff_start_tag(pb
, "data");
144 static int wav_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
146 AVIOContext
*pb
= s
->pb
;
147 WAVMuxContext
*wav
= s
->priv_data
;
148 avio_write(pb
, pkt
->data
, pkt
->size
);
149 if(pkt
->pts
!= AV_NOPTS_VALUE
) {
150 wav
->minpts
= FFMIN(wav
->minpts
, pkt
->pts
);
151 wav
->maxpts
= FFMAX(wav
->maxpts
, pkt
->pts
);
152 wav
->last_duration
= pkt
->duration
;
154 av_log(s
, AV_LOG_ERROR
, "wav_write_packet: NOPTS\n");
158 static int wav_write_trailer(AVFormatContext
*s
)
160 AVIOContext
*pb
= s
->pb
;
161 WAVMuxContext
*wav
= s
->priv_data
;
166 if (s
->pb
->seekable
) {
167 ff_end_tag(pb
, wav
->data
);
169 /* update file size */
170 file_size
= avio_tell(pb
);
171 avio_seek(pb
, 4, SEEK_SET
);
172 avio_wl32(pb
, (uint32_t)(file_size
- 8));
173 avio_seek(pb
, file_size
, SEEK_SET
);
177 if(s
->streams
[0]->codec
->codec_tag
!= 0x01) {
178 /* Update num_samps in fact chunk */
179 int number_of_samples
;
180 number_of_samples
= av_rescale(wav
->maxpts
- wav
->minpts
+ wav
->last_duration
,
181 s
->streams
[0]->codec
->sample_rate
* (int64_t)s
->streams
[0]->time_base
.num
,
182 s
->streams
[0]->time_base
.den
);
183 avio_seek(pb
, wav
->fact_pos
, SEEK_SET
);
184 avio_wl32(pb
, number_of_samples
);
185 avio_seek(pb
, file_size
, SEEK_SET
);
192 #define OFFSET(x) offsetof(WAVMuxContext, x)
193 #define ENC AV_OPT_FLAG_ENCODING_PARAM
194 static const AVOption options
[] = {
195 { "write_bext", "Write BEXT chunk.", OFFSET(write_bext
), AV_OPT_TYPE_INT
, { .i64
= 0 }, 0, 1, ENC
},
199 static const AVClass wav_muxer_class
= {
200 .class_name
= "WAV muxer",
201 .item_name
= av_default_item_name
,
203 .version
= LIBAVUTIL_VERSION_INT
,
206 AVOutputFormat ff_wav_muxer
= {
208 .long_name
= NULL_IF_CONFIG_SMALL("WAV / WAVE (Waveform Audio)"),
209 .mime_type
= "audio/x-wav",
211 .priv_data_size
= sizeof(WAVMuxContext
),
212 .audio_codec
= AV_CODEC_ID_PCM_S16LE
,
213 .video_codec
= AV_CODEC_ID_NONE
,
214 .write_header
= wav_write_header
,
215 .write_packet
= wav_write_packet
,
216 .write_trailer
= wav_write_trailer
,
217 .flags
= AVFMT_TS_NONSTRICT
,
218 .codec_tag
= (const AVCodecTag
* const []){ ff_codec_wav_tags
, 0 },
219 .priv_class
= &wav_muxer_class
,