Libav
riffenc.c
Go to the documentation of this file.
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 */
51 {
52  int bps, blkalign, bytespersec, frame_size;
53  int hdrsize = 18;
54  int waveformatextensible;
55  uint8_t temp[256];
56  uint8_t *riff_extradata = temp;
57  uint8_t *riff_extradata_start = temp;
58 
59  if (!enc->codec_tag || enc->codec_tag > 0xffff)
60  return -1;
61 
62  /* We use the known constant frame size for the codec if known, otherwise
63  * fall back on using AVCodecContext.frame_size, which is not as reliable
64  * for indicating packet duration. */
65  frame_size = av_get_audio_frame_duration(enc, 0);
66  if (!frame_size)
67  frame_size = enc->frame_size;
68 
69  waveformatextensible = (enc->channels > 2 && enc->channel_layout) ||
70  enc->sample_rate > 48000 ||
72 
73  if (waveformatextensible)
74  avio_wl16(pb, 0xfffe);
75  else
76  avio_wl16(pb, enc->codec_tag);
77 
78  avio_wl16(pb, enc->channels);
79  avio_wl32(pb, enc->sample_rate);
80  if (enc->codec_id == AV_CODEC_ID_MP2 ||
81  enc->codec_id == AV_CODEC_ID_MP3 ||
82  enc->codec_id == AV_CODEC_ID_GSM_MS) {
83  bps = 0;
84  } else {
85  if (!(bps = av_get_bits_per_sample(enc->codec_id))) {
86  if (enc->bits_per_coded_sample)
87  bps = enc->bits_per_coded_sample;
88  else
89  bps = 16; // default to 16
90  }
91  }
92  if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) {
94  "requested bits_per_coded_sample (%d) "
95  "and actually stored (%d) differ\n",
96  enc->bits_per_coded_sample, bps);
97  }
98 
99  if (enc->codec_id == AV_CODEC_ID_MP2 ||
100  enc->codec_id == AV_CODEC_ID_MP3) {
101  /* This is wrong, but it seems many demuxers do not work if this
102  * is set correctly. */
103  blkalign = frame_size;
104  // blkalign = 144 * enc->bit_rate/enc->sample_rate;
105  } else if (enc->codec_id == AV_CODEC_ID_AC3) {
106  blkalign = 3840; /* maximum bytes per frame */
107  } else if (enc->block_align != 0) { /* specified by the codec */
108  blkalign = enc->block_align;
109  } else
110  blkalign = bps * enc->channels / av_gcd(8, bps);
111  if (enc->codec_id == AV_CODEC_ID_PCM_U8 ||
117  bytespersec = enc->sample_rate * blkalign;
118  } else {
119  bytespersec = enc->bit_rate / 8;
120  }
121  avio_wl32(pb, bytespersec); /* bytes per second */
122  avio_wl16(pb, blkalign); /* block align */
123  avio_wl16(pb, bps); /* bits per sample */
124  if (enc->codec_id == AV_CODEC_ID_MP3) {
125  hdrsize += 12;
126  bytestream_put_le16(&riff_extradata, 1); /* wID */
127  bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */
128  bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */
129  bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */
130  bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */
131  } else if (enc->codec_id == AV_CODEC_ID_MP2) {
132  hdrsize += 22;
133  /* fwHeadLayer */
134  bytestream_put_le16(&riff_extradata, 2);
135  /* dwHeadBitrate */
136  bytestream_put_le32(&riff_extradata, enc->bit_rate);
137  /* fwHeadMode */
138  bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8);
139  /* fwHeadModeExt */
140  bytestream_put_le16(&riff_extradata, 0);
141  /* wHeadEmphasis */
142  bytestream_put_le16(&riff_extradata, 1);
143  /* fwHeadFlags */
144  bytestream_put_le16(&riff_extradata, 16);
145  /* dwPTSLow */
146  bytestream_put_le32(&riff_extradata, 0);
147  /* dwPTSHigh */
148  bytestream_put_le32(&riff_extradata, 0);
149  } else if (enc->codec_id == AV_CODEC_ID_GSM_MS ||
151  hdrsize += 2;
152  /* wSamplesPerBlock */
153  bytestream_put_le16(&riff_extradata, frame_size);
154  } else if (enc->extradata_size) {
155  riff_extradata_start = enc->extradata;
156  riff_extradata = enc->extradata + enc->extradata_size;
157  hdrsize += enc->extradata_size;
158  }
159  /* write WAVEFORMATEXTENSIBLE extensions */
160  if (waveformatextensible) {
161  hdrsize += 22;
162  /* 22 is WAVEFORMATEXTENSIBLE size */
163  avio_wl16(pb, riff_extradata - riff_extradata_start + 22);
164  /* ValidBitsPerSample || SamplesPerBlock || Reserved */
165  avio_wl16(pb, bps);
166  /* dwChannelMask */
167  avio_wl32(pb, enc->channel_layout);
168  /* GUID + next 3 */
169  avio_wl32(pb, enc->codec_tag);
170  avio_wl32(pb, 0x00100000);
171  avio_wl32(pb, 0xAA000080);
172  avio_wl32(pb, 0x719B3800);
173  } else {
174  avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */
175  }
176  avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start);
177  if (hdrsize & 1) {
178  hdrsize++;
179  avio_w8(pb, 0);
180  }
181 
182  return hdrsize;
183 }
184 
185 /* BITMAPINFOHEADER header */
187  const AVCodecTag *tags, int for_asf)
188 {
189  /* size */
190  avio_wl32(pb, 40 + enc->extradata_size);
191  avio_wl32(pb, enc->width);
192  //We always store RGB TopDown
193  avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height);
194  /* planes */
195  avio_wl16(pb, 1);
196  /* depth */
198  /* compression type */
199  avio_wl32(pb, enc->codec_tag);
200  avio_wl32(pb, enc->width * enc->height * 3);
201  avio_wl32(pb, 0);
202  avio_wl32(pb, 0);
203  avio_wl32(pb, 0);
204  avio_wl32(pb, 0);
205 
206  avio_write(pb, enc->extradata, enc->extradata_size);
207 
208  if (!for_asf && enc->extradata_size & 1)
209  avio_w8(pb, 0);
210 }
211 
212 void ff_parse_specific_params(AVCodecContext *stream, int *au_rate,
213  int *au_ssize, int *au_scale)
214 {
215  int gcd;
216  int audio_frame_size;
217 
218  /* We use the known constant frame size for the codec if known, otherwise
219  * fall back on using AVCodecContext.frame_size, which is not as reliable
220  * for indicating packet duration. */
221  audio_frame_size = av_get_audio_frame_duration(stream, 0);
222  if (!audio_frame_size)
223  audio_frame_size = stream->frame_size;
224 
225  *au_ssize = stream->block_align;
226  if (audio_frame_size && stream->sample_rate) {
227  *au_scale = audio_frame_size;
228  *au_rate = stream->sample_rate;
229  } else if (stream->codec_type == AVMEDIA_TYPE_VIDEO ||
230  stream->codec_type == AVMEDIA_TYPE_DATA ||
231  stream->codec_type == AVMEDIA_TYPE_SUBTITLE) {
232  *au_scale = stream->time_base.num;
233  *au_rate = stream->time_base.den;
234  } else {
235  *au_scale = stream->block_align ? stream->block_align * 8 : 8;
236  *au_rate = stream->bit_rate ? stream->bit_rate :
237  8 * stream->sample_rate;
238  }
239  gcd = av_gcd(*au_scale, *au_rate);
240  *au_scale /= gcd;
241  *au_rate /= gcd;
242 }
243 
244 void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str)
245 {
246  int len = strlen(str);
247  if (len > 0) {
248  len++;
249  ffio_wfourcc(pb, tag);
250  avio_wl32(pb, len);
251  avio_put_str(pb, str);
252  if (len & 1)
253  avio_w8(pb, 0);
254  }
255 }
256 
257 static const char riff_tags[][5] = {
258  "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI",
259  "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD",
260  "IPRT", "ISBJ", "ISFT", "ISHP", "ISRC", "ISRF", "ITCH",
261  { 0 }
262 };
263 
265 {
266  int i;
267 
268  for (i = 0; *riff_tags[i]; i++)
270  return 1;
271 
272  return 0;
273 }
274 
276 {
277  AVIOContext *pb = s->pb;
278  int i;
279  int64_t list_pos;
281 
283 
284  /* writing empty LIST is not nice and may cause problems */
285  if (!riff_has_valid_tags(s))
286  return;
287 
288  list_pos = ff_start_tag(pb, "LIST");
289  ffio_wfourcc(pb, "INFO");
290  for (i = 0; *riff_tags[i]; i++)
291  if ((t = av_dict_get(s->metadata, riff_tags[i],
293  ff_riff_write_info_tag(s->pb, t->key, t->value);
294  ff_end_tag(pb, list_pos);
295 }