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"
32 #include "avformat.h"
33 #include "internal.h"
34 #include "oggdec.h"
35 #include "vorbiscomment.h"
36 
37 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
38 {
39  int i, cnum, h, m, s, ms, keylen = strlen(key);
40  AVChapter *chapter = NULL;
41 
42  if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
43  return 0;
44 
45  if (keylen == 9) {
46  if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
47  return 0;
48 
49  avpriv_new_chapter(as, cnum, (AVRational){1,1000},
50  ms + 1000*(s + 60*(m + 60*h)),
52  av_free(val);
53  } else if (!strcmp(key+9, "NAME")) {
54  for(i = 0; i < as->nb_chapters; i++)
55  if (as->chapters[i]->id == cnum) {
56  chapter = as->chapters[i];
57  break;
58  }
59  if (!chapter)
60  return 0;
61 
62  av_dict_set(&chapter->metadata, "title", val,
64  } else
65  return 0;
66 
67  av_free(key);
68  return 1;
69 }
70 
71 int
73 {
74  const uint8_t *p = buf;
75  const uint8_t *end = buf + size;
76  unsigned n, j;
77  int s;
78 
79  if (size < 8) /* must have vendor_length and user_comment_list_length */
80  return -1;
81 
82  s = bytestream_get_le32(&p);
83 
84  if (end - p - 4 < s || s < 0)
85  return -1;
86 
87  p += s;
88 
89  n = bytestream_get_le32(&p);
90 
91  while (end - p >= 4 && n > 0) {
92  const char *t, *v;
93  int tl, vl;
94 
95  s = bytestream_get_le32(&p);
96 
97  if (end - p < s || s < 0)
98  break;
99 
100  t = p;
101  p += s;
102  n--;
103 
104  v = memchr(t, '=', s);
105  if (!v)
106  continue;
107 
108  tl = v - t;
109  vl = s - tl - 1;
110  v++;
111 
112  if (tl && vl) {
113  char *tt, *ct;
114 
115  tt = av_malloc(tl + 1);
116  ct = av_malloc(vl + 1);
117  if (!tt || !ct) {
118  av_freep(&tt);
119  av_freep(&ct);
120  av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
121  continue;
122  }
123 
124  for (j = 0; j < tl; j++)
125  tt[j] = toupper(t[j]);
126  tt[tl] = 0;
127 
128  memcpy(ct, v, vl);
129  ct[vl] = 0;
130 
131  if (!ogm_chapter(as, tt, ct))
132  av_dict_set(m, tt, ct,
135  }
136  }
137 
138  if (p != end)
139  av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
140  if (n > 0)
141  av_log(as, AV_LOG_INFO,
142  "truncated comment header, %i comments not found\n", n);
143 
145 
146  return 0;
147 }
148 
149 
164  unsigned int len[3];
165  unsigned char *packet[3];
167  int64_t final_pts;
169 };
170 
171 
172 static unsigned int
174  uint8_t **buf)
175 {
176  int i,offset, len;
177  unsigned char *ptr;
178 
179  len = priv->len[0] + priv->len[1] + priv->len[2];
180  ptr = *buf = av_mallocz(len + len/255 + 64);
181 
182  ptr[0] = 2;
183  offset = 1;
184  offset += av_xiphlacing(&ptr[offset], priv->len[0]);
185  offset += av_xiphlacing(&ptr[offset], priv->len[1]);
186  for (i = 0; i < 3; i++) {
187  memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
188  offset += priv->len[i];
189  av_freep(&priv->packet[i]);
190  }
191  *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
192  return offset;
193 }
194 
195 static void vorbis_cleanup(AVFormatContext *s, int idx)
196 {
197  struct ogg *ogg = s->priv_data;
198  struct ogg_stream *os = ogg->streams + idx;
199  struct oggvorbis_private *priv = os->private;
200  int i;
201  if (os->private)
202  for (i = 0; i < 3; i++)
203  av_freep(&priv->packet[i]);
204 }
205 
206 static int
208 {
209  struct ogg *ogg = s->priv_data;
210  struct ogg_stream *os = ogg->streams + idx;
211  AVStream *st = s->streams[idx];
212  struct oggvorbis_private *priv;
213  int pkt_type = os->buf[os->pstart];
214 
215  if (!os->private) {
216  os->private = av_mallocz(sizeof(struct oggvorbis_private));
217  if (!os->private)
218  return 0;
219  }
220 
221  if (!(pkt_type & 1))
222  return 0;
223 
224  if (os->psize < 1 || pkt_type > 5)
225  return -1;
226 
227  priv = os->private;
228 
229  if (priv->packet[pkt_type>>1])
230  return -1;
231  if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
232  return -1;
233 
234  priv->len[pkt_type >> 1] = os->psize;
235  priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
236  memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
237  if (os->buf[os->pstart] == 1) {
238  const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
239  unsigned blocksize, bs0, bs1;
240  int srate;
241 
242  if (os->psize != 30)
243  return -1;
244 
245  if (bytestream_get_le32(&p) != 0) /* vorbis_version */
246  return -1;
247 
248  st->codec->channels = bytestream_get_byte(&p);
249  srate = bytestream_get_le32(&p);
250  p += 4; // skip maximum bitrate
251  st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
252  p += 4; // skip minimum bitrate
253 
254  blocksize = bytestream_get_byte(&p);
255  bs0 = blocksize & 15;
256  bs1 = blocksize >> 4;
257 
258  if (bs0 > bs1)
259  return -1;
260  if (bs0 < 6 || bs1 > 13)
261  return -1;
262 
263  if (bytestream_get_byte(&p) != 1) /* framing_flag */
264  return -1;
265 
268 
269  if (srate > 0) {
270  st->codec->sample_rate = srate;
271  avpriv_set_pts_info(st, 64, 1, srate);
272  }
273  } else if (os->buf[os->pstart] == 3) {
274  if (os->psize > 8 &&
275  ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
276  // drop all metadata we parsed and which is not required by libvorbis
277  unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
278  if (new_len >= 16 && new_len < os->psize) {
279  AV_WL32(priv->packet[1] + new_len - 5, 0);
280  priv->packet[1][new_len - 1] = 1;
281  priv->len[1] = new_len;
282  }
283  }
284  } else {
285  int ret;
286  st->codec->extradata_size =
287  fixup_vorbis_headers(s, priv, &st->codec->extradata);
288  if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) {
289  av_freep(&st->codec->extradata);
290  st->codec->extradata_size = 0;
291  return ret;
292  }
293  }
294 
295  return 1;
296 }
297 
298 static int vorbis_packet(AVFormatContext *s, int idx)
299 {
300  struct ogg *ogg = s->priv_data;
301  struct ogg_stream *os = ogg->streams + idx;
302  struct oggvorbis_private *priv = os->private;
303  int duration;
304 
305  /* first packet handling
306  here we parse the duration of each packet in the first page and compare
307  the total duration to the page granule to find the encoder delay and
308  set the first timestamp */
309  if (!os->lastpts) {
310  int seg;
311  uint8_t *last_pkt = os->buf + os->pstart;
312  uint8_t *next_pkt = last_pkt;
313  int first_duration = 0;
314 
316  duration = 0;
317  for (seg = 0; seg < os->nsegs; seg++) {
318  if (os->segments[seg] < 255) {
319  int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
320  if (d < 0) {
321  duration = os->granule;
322  break;
323  }
324  if (!duration)
325  first_duration = d;
326  duration += d;
327  last_pkt = next_pkt + os->segments[seg];
328  }
329  next_pkt += os->segments[seg];
330  }
331  os->lastpts = os->lastdts = os->granule - duration;
332  s->streams[idx]->start_time = os->lastpts + first_duration;
333  if (s->streams[idx]->duration)
334  s->streams[idx]->duration -= s->streams[idx]->start_time;
335  s->streams[idx]->cur_dts = AV_NOPTS_VALUE;
336  priv->final_pts = AV_NOPTS_VALUE;
338  }
339 
340  /* parse packet duration */
341  if (os->psize > 0) {
342  duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
343  if (duration <= 0) {
345  return 0;
346  }
347  os->pduration = duration;
348  }
349 
350  /* final packet handling
351  here we save the pts of the first packet in the final page, sum up all
352  packet durations in the final page except for the last one, and compare
353  to the page granule to find the duration of the final packet */
354  if (os->flags & OGG_FLAG_EOS) {
355  if (os->lastpts != AV_NOPTS_VALUE) {
356  priv->final_pts = os->lastpts;
357  priv->final_duration = 0;
358  }
359  if (os->segp == os->nsegs)
360  os->pduration = os->granule - priv->final_pts - priv->final_duration;
361  priv->final_duration += os->pduration;
362  }
363 
364  return 0;
365 }
366 
367 const struct ogg_codec ff_vorbis_codec = {
368  .magic = "\001vorbis",
369  .magicsize = 7,
370  .header = vorbis_header,
371  .packet = vorbis_packet,
372  .cleanup= vorbis_cleanup,
373  .nb_header = 3,
374 };