]> git.sesse.net Git - ffmpeg/blob - libavformat/riffenc.c
crypto: consistently use size_t as type for length parameters
[ffmpeg] / libavformat / riffenc.c
1 /*
2  * RIFF muxing functions
3  * Copyright (c) 2000 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "libavutil/dict.h"
23 #include "libavutil/log.h"
24 #include "libavutil/mathematics.h"
25 #include "libavcodec/avcodec.h"
26 #include "libavcodec/bytestream.h"
27 #include "avformat.h"
28 #include "avio_internal.h"
29 #include "riff.h"
30
31 int64_t ff_start_tag(AVIOContext *pb, const char *tag)
32 {
33     ffio_wfourcc(pb, tag);
34     avio_wl32(pb, 0);
35     return avio_tell(pb);
36 }
37
38 void ff_end_tag(AVIOContext *pb, int64_t start)
39 {
40     int64_t pos;
41
42     pos = avio_tell(pb);
43     avio_seek(pb, start - 4, SEEK_SET);
44     avio_wl32(pb, (uint32_t)(pos - start));
45     avio_seek(pb, pos, SEEK_SET);
46 }
47
48 /* WAVEFORMATEX header */
49 /* returns the size or -1 on error */
50 int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb,
51                       AVCodecParameters *par)
52 {
53     int bps, blkalign, bytespersec, frame_size;
54     int hdrsize = 18;
55     int waveformatextensible;
56     uint8_t temp[256];
57     uint8_t *riff_extradata       = temp;
58     uint8_t *riff_extradata_start = temp;
59
60     if (!par->codec_tag || par->codec_tag > 0xffff)
61         return -1;
62
63     /* We use the known constant frame size for the codec if known, otherwise
64      * fall back on using AVCodecContext.frame_size, which is not as reliable
65      * for indicating packet duration. */
66     frame_size = av_get_audio_frame_duration2(par, par->block_align);
67
68     waveformatextensible = (par->channels > 2 && par->channel_layout) ||
69                            par->sample_rate > 48000 ||
70                            av_get_bits_per_sample(par->codec_id) > 16;
71
72     if (waveformatextensible)
73         avio_wl16(pb, 0xfffe);
74     else
75         avio_wl16(pb, par->codec_tag);
76
77     avio_wl16(pb, par->channels);
78     avio_wl32(pb, par->sample_rate);
79     if (par->codec_id == AV_CODEC_ID_MP2 ||
80         par->codec_id == AV_CODEC_ID_MP3 ||
81         par->codec_id == AV_CODEC_ID_GSM_MS) {
82         bps = 0;
83     } else {
84         if (!(bps = av_get_bits_per_sample(par->codec_id))) {
85             if (par->bits_per_coded_sample)
86                 bps = par->bits_per_coded_sample;
87             else
88                 bps = 16;  // default to 16
89         }
90     }
91     if (bps != par->bits_per_coded_sample && par->bits_per_coded_sample) {
92         av_log(s, AV_LOG_WARNING,
93                "requested bits_per_coded_sample (%d) "
94                "and actually stored (%d) differ\n",
95                par->bits_per_coded_sample, bps);
96     }
97
98     if (par->codec_id == AV_CODEC_ID_MP2) {
99         blkalign = frame_size;
100     } else if (par->codec_id == AV_CODEC_ID_MP3) {
101         blkalign = 576 * (par->sample_rate <= 24000 ? 1 : 2);
102     } else if (par->codec_id == AV_CODEC_ID_AC3) {
103         blkalign = 3840;                /* maximum bytes per frame */
104     } else if (par->block_align != 0) { /* specified by the codec */
105         blkalign = par->block_align;
106     } else
107         blkalign = bps * par->channels / av_gcd(8, bps);
108     if (par->codec_id == AV_CODEC_ID_PCM_U8 ||
109         par->codec_id == AV_CODEC_ID_PCM_S24LE ||
110         par->codec_id == AV_CODEC_ID_PCM_S32LE ||
111         par->codec_id == AV_CODEC_ID_PCM_F32LE ||
112         par->codec_id == AV_CODEC_ID_PCM_F64LE ||
113         par->codec_id == AV_CODEC_ID_PCM_S16LE) {
114         bytespersec = par->sample_rate * blkalign;
115     } else {
116         bytespersec = par->bit_rate / 8;
117     }
118     avio_wl32(pb, bytespersec); /* bytes per second */
119     avio_wl16(pb, blkalign);    /* block align */
120     avio_wl16(pb, bps);         /* bits per sample */
121     if (par->codec_id == AV_CODEC_ID_MP3) {
122         hdrsize += 12;
123         bytestream_put_le16(&riff_extradata, 1);    /* wID */
124         bytestream_put_le32(&riff_extradata, 2);    /* fdwFlags */
125         bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
126         bytestream_put_le16(&riff_extradata, 1);    /* nFramesPerBlock */
127         bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
128     } else if (par->codec_id == AV_CODEC_ID_MP2) {
129         hdrsize += 22;
130         /* fwHeadLayer */
131         bytestream_put_le16(&riff_extradata, 2);
132         /* dwHeadBitrate */
133         bytestream_put_le32(&riff_extradata, par->bit_rate);
134         /* fwHeadMode */
135         bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8);
136         /* fwHeadModeExt */
137         bytestream_put_le16(&riff_extradata, 0);
138         /* wHeadEmphasis */
139         bytestream_put_le16(&riff_extradata, 1);
140         /* fwHeadFlags */
141         bytestream_put_le16(&riff_extradata, 16);
142         /* dwPTSLow */
143         bytestream_put_le32(&riff_extradata, 0);
144         /* dwPTSHigh */
145         bytestream_put_le32(&riff_extradata, 0);
146     } else if (par->codec_id == AV_CODEC_ID_GSM_MS ||
147                par->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) {
148         hdrsize += 2;
149         /* wSamplesPerBlock */
150         bytestream_put_le16(&riff_extradata, frame_size);
151     } else if (par->extradata_size) {
152         riff_extradata_start = par->extradata;
153         riff_extradata       = par->extradata + par->extradata_size;
154         hdrsize             += par->extradata_size;
155     }
156     /* write WAVEFORMATEXTENSIBLE extensions */
157     if (waveformatextensible) {
158         hdrsize += 22;
159         /* 22 is WAVEFORMATEXTENSIBLE size */
160         avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
161         /* ValidBitsPerSample || SamplesPerBlock || Reserved */
162         avio_wl16(pb, bps);
163         /* dwChannelMask */
164         avio_wl32(pb, par->channel_layout);
165         /* GUID + next 3 */
166         avio_wl32(pb, par->codec_tag);
167         avio_wl32(pb, 0x00100000);
168         avio_wl32(pb, 0xAA000080);
169         avio_wl32(pb, 0x719B3800);
170     } else {
171         avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
172     }
173     avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
174     if (hdrsize & 1) {
175         hdrsize++;
176         avio_w8(pb, 0);
177     }
178
179     return hdrsize;
180 }
181
182 /* BITMAPINFOHEADER header */
183 void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par,
184                        const AVCodecTag *tags, int for_asf)
185 {
186     /* size */
187     avio_wl32(pb, 40 + par->extradata_size);
188     avio_wl32(pb, par->width);
189     //We always store RGB TopDown
190     avio_wl32(pb, par->codec_tag ? par->height : -par->height);
191     /* planes */
192     avio_wl16(pb, 1);
193     /* depth */
194     avio_wl16(pb, par->bits_per_coded_sample ? par->bits_per_coded_sample : 24);
195     /* compression type */
196     avio_wl32(pb, par->codec_tag);
197     avio_wl32(pb, par->width * par->height * 3);
198     avio_wl32(pb, 0);
199     avio_wl32(pb, 0);
200     avio_wl32(pb, 0);
201     avio_wl32(pb, 0);
202
203     avio_write(pb, par->extradata, par->extradata_size);
204
205     if (!for_asf && par->extradata_size & 1)
206         avio_w8(pb, 0);
207 }
208
209 void ff_parse_specific_params(AVStream *st, int *au_rate,
210                               int *au_ssize, int *au_scale)
211 {
212     AVCodecParameters *par = st->codecpar;
213     int gcd;
214     int audio_frame_size;
215
216     audio_frame_size = av_get_audio_frame_duration2(par, 0);
217
218     *au_ssize = par->block_align;
219     if (audio_frame_size && par->sample_rate) {
220         *au_scale = audio_frame_size;
221         *au_rate  = par->sample_rate;
222     } else if (par->codec_type == AVMEDIA_TYPE_VIDEO ||
223                par->codec_type == AVMEDIA_TYPE_DATA ||
224                par->codec_type == AVMEDIA_TYPE_SUBTITLE) {
225         *au_scale = st->time_base.num;
226         *au_rate  = st->time_base.den;
227     } else {
228         *au_scale = par->block_align ? par->block_align * 8 : 8;
229         *au_rate  = par->bit_rate ? par->bit_rate :
230                     8 * par->sample_rate;
231     }
232     gcd        = av_gcd(*au_scale, *au_rate);
233     *au_scale /= gcd;
234     *au_rate  /= gcd;
235 }
236
237 void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str)
238 {
239     int len = strlen(str);
240     if (len > 0) {
241         len++;
242         ffio_wfourcc(pb, tag);
243         avio_wl32(pb, len);
244         avio_put_str(pb, str);
245         if (len & 1)
246             avio_w8(pb, 0);
247     }
248 }
249
250 static const char riff_tags[][5] = {
251     "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
252     "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
253     "IPRT", "ITRK", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH",
254     { 0 }
255 };
256
257 static int riff_has_valid_tags(AVFormatContext *s)
258 {
259     int i;
260
261     for (i = 0; *riff_tags[i]; i++)
262         if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE))
263             return 1;
264
265     return 0;
266 }
267
268 void ff_riff_write_info(AVFormatContext *s)
269 {
270     AVIOContext *pb = s->pb;
271     int i;
272     int64_t list_pos;
273     AVDictionaryEntry *t = NULL;
274
275     ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL);
276
277     /* writing empty LIST is not nice and may cause problems */
278     if (!riff_has_valid_tags(s))
279         return;
280
281     list_pos = ff_start_tag(pb, "LIST");
282     ffio_wfourcc(pb, "INFO");
283     for (i = 0; *riff_tags[i]; i++)
284         if ((t = av_dict_get(s->metadata, riff_tags[i],
285                              NULL, AV_DICT_MATCH_CASE)))
286             ff_riff_write_info_tag(s->pb, t->key, t->value);
287     ff_end_tag(pb, list_pos);
288 }