oggparsevorbis.c
Go to the documentation of this file.
1 
25 #include <stdlib.h>
26 #include "libavutil/avstring.h"
27 #include "libavutil/bswap.h"
28 #include "libavutil/dict.h"
29 #include "libavcodec/get_bits.h"
30 #include "libavcodec/bytestream.h"
31 #include "avformat.h"
32 #include "internal.h"
33 #include "oggdec.h"
34 #include "vorbiscomment.h"
35 
36 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
37 {
38  int i, cnum, h, m, s, ms, keylen = strlen(key);
39  AVChapter *chapter = NULL;
40 
41  if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
42  return 0;
43 
44  if (keylen == 9) {
45  if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
46  return 0;
47 
48  avpriv_new_chapter(as, cnum, (AVRational){1,1000},
49  ms + 1000*(s + 60*(m + 60*h)),
51  av_free(val);
52  } else if (!strcmp(key+9, "NAME")) {
53  for(i = 0; i < as->nb_chapters; i++)
54  if (as->chapters[i]->id == cnum) {
55  chapter = as->chapters[i];
56  break;
57  }
58  if (!chapter)
59  return 0;
60 
61  av_dict_set(&chapter->metadata, "title", val,
63  } else
64  return 0;
65 
66  av_free(key);
67  return 1;
68 }
69 
70 int
71 ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size)
72 {
73  const uint8_t *p = buf;
74  const uint8_t *end = buf + size;
75  unsigned n, j;
76  int s;
77 
78  if (size < 8) /* must have vendor_length and user_comment_list_length */
79  return -1;
80 
81  s = bytestream_get_le32(&p);
82 
83  if (end - p - 4 < s || s < 0)
84  return -1;
85 
86  p += s;
87 
88  n = bytestream_get_le32(&p);
89 
90  while (end - p >= 4 && n > 0) {
91  const char *t, *v;
92  int tl, vl;
93 
94  s = bytestream_get_le32(&p);
95 
96  if (end - p < s || s < 0)
97  break;
98 
99  t = p;
100  p += s;
101  n--;
102 
103  v = memchr(t, '=', s);
104  if (!v)
105  continue;
106 
107  tl = v - t;
108  vl = s - tl - 1;
109  v++;
110 
111  if (tl && vl) {
112  char *tt, *ct;
113 
114  tt = av_malloc(tl + 1);
115  ct = av_malloc(vl + 1);
116  if (!tt || !ct) {
117  av_freep(&tt);
118  av_freep(&ct);
119  av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
120  continue;
121  }
122 
123  for (j = 0; j < tl; j++)
124  tt[j] = toupper(t[j]);
125  tt[tl] = 0;
126 
127  memcpy(ct, v, vl);
128  ct[vl] = 0;
129 
130  if (!ogm_chapter(as, tt, ct))
131  av_dict_set(m, tt, ct,
134  }
135  }
136 
137  if (p != end)
138  av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
139  if (n > 0)
140  av_log(as, AV_LOG_INFO,
141  "truncated comment header, %i comments not found\n", n);
142 
144 
145  return 0;
146 }
147 
148 
163  unsigned int len[3];
164  unsigned char *packet[3];
165 };
166 
167 
168 static unsigned int
170  uint8_t **buf)
171 {
172  int i,offset, len;
173  unsigned char *ptr;
174 
175  len = priv->len[0] + priv->len[1] + priv->len[2];
176  ptr = *buf = av_mallocz(len + len/255 + 64);
177 
178  ptr[0] = 2;
179  offset = 1;
180  offset += av_xiphlacing(&ptr[offset], priv->len[0]);
181  offset += av_xiphlacing(&ptr[offset], priv->len[1]);
182  for (i = 0; i < 3; i++) {
183  memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
184  offset += priv->len[i];
185  av_freep(&priv->packet[i]);
186  }
187  *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
188  return offset;
189 }
190 
191 
192 static int
194 {
195  struct ogg *ogg = s->priv_data;
196  struct ogg_stream *os = ogg->streams + idx;
197  AVStream *st = s->streams[idx];
198  struct oggvorbis_private *priv;
199  int pkt_type = os->buf[os->pstart];
200 
201  if (!(pkt_type & 1))
202  return 0;
203 
204  if (!os->private) {
205  os->private = av_mallocz(sizeof(struct oggvorbis_private));
206  if (!os->private)
207  return 0;
208  }
209 
210  if (os->psize < 1 || pkt_type > 5)
211  return -1;
212 
213  priv = os->private;
214 
215  if (priv->packet[pkt_type>>1])
216  return -1;
217  if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
218  return -1;
219 
220  priv->len[pkt_type >> 1] = os->psize;
221  priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
222  memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
223  if (os->buf[os->pstart] == 1) {
224  const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
225  unsigned blocksize, bs0, bs1;
226  int srate;
227 
228  if (os->psize != 30)
229  return -1;
230 
231  if (bytestream_get_le32(&p) != 0) /* vorbis_version */
232  return -1;
233 
234  st->codec->channels = bytestream_get_byte(&p);
235  srate = bytestream_get_le32(&p);
236  p += 4; // skip maximum bitrate
237  st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
238  p += 4; // skip minimum bitrate
239 
240  blocksize = bytestream_get_byte(&p);
241  bs0 = blocksize & 15;
242  bs1 = blocksize >> 4;
243 
244  if (bs0 > bs1)
245  return -1;
246  if (bs0 < 6 || bs1 > 13)
247  return -1;
248 
249  if (bytestream_get_byte(&p) != 1) /* framing_flag */
250  return -1;
251 
254 
255  if (srate > 0) {
256  st->codec->sample_rate = srate;
257  avpriv_set_pts_info(st, 64, 1, srate);
258  }
259  } else if (os->buf[os->pstart] == 3) {
260  if (os->psize > 8 &&
261  ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
262  // drop all metadata we parsed and which is not required by libvorbis
263  unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
264  if (new_len >= 16 && new_len < os->psize) {
265  AV_WL32(priv->packet[1] + new_len - 5, 0);
266  priv->packet[1][new_len - 1] = 1;
267  priv->len[1] = new_len;
268  }
269  }
270  } else {
271  st->codec->extradata_size =
272  fixup_vorbis_headers(s, priv, &st->codec->extradata);
273  }
274 
275  return 1;
276 }
277 
278 const struct ogg_codec ff_vorbis_codec = {
279  .magic = "\001vorbis",
280  .magicsize = 7,
281  .header = vorbis_header
282 };