oggdec.c
Go to the documentation of this file.
1 /*
2  * Ogg bitstream support
3  * Luca Barbato <lu_zero@gentoo.org>
4  * Based on tcvp implementation
5  */
6 
7 /*
8  Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
9 
10  Permission is hereby granted, free of charge, to any person
11  obtaining a copy of this software and associated documentation
12  files (the "Software"), to deal in the Software without
13  restriction, including without limitation the rights to use, copy,
14  modify, merge, publish, distribute, sublicense, and/or sell copies
15  of the Software, and to permit persons to whom the Software is
16  furnished to do so, subject to the following conditions:
17 
18  The above copyright notice and this permission notice shall be
19  included in all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  DEALINGS IN THE SOFTWARE.
29  */
30 
31 
32 #include <stdio.h>
33 #include "oggdec.h"
34 #include "avformat.h"
35 #include "internal.h"
36 #include "vorbiscomment.h"
37 
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40 
41 static const struct ogg_codec * const ogg_codecs[] = {
56  NULL
57 };
58 
59 //FIXME We could avoid some structure duplication
60 static int ogg_save(AVFormatContext *s)
61 {
62  struct ogg *ogg = s->priv_data;
63  struct ogg_state *ost =
64  av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
65  int i;
66  ost->pos = avio_tell(s->pb);
67  ost->curidx = ogg->curidx;
68  ost->next = ogg->state;
69  ost->nstreams = ogg->nstreams;
70  memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
71 
72  for (i = 0; i < ogg->nstreams; i++) {
73  struct ogg_stream *os = ogg->streams + i;
75  memcpy(os->buf, ost->streams[i].buf, os->bufpos);
76  }
77 
78  ogg->state = ost;
79 
80  return 0;
81 }
82 
83 static int ogg_restore(AVFormatContext *s, int discard)
84 {
85  struct ogg *ogg = s->priv_data;
86  AVIOContext *bc = s->pb;
87  struct ogg_state *ost = ogg->state;
88  int i;
89 
90  if (!ost)
91  return 0;
92 
93  ogg->state = ost->next;
94 
95  if (!discard) {
96  struct ogg_stream *old_streams = ogg->streams;
97 
98  for (i = 0; i < ogg->nstreams; i++)
99  av_free(ogg->streams[i].buf);
100 
101  avio_seek(bc, ost->pos, SEEK_SET);
102  ogg->curidx = ost->curidx;
103  ogg->nstreams = ost->nstreams;
104  ogg->streams = av_realloc(ogg->streams,
105  ogg->nstreams * sizeof(*ogg->streams));
106 
107  if (ogg->streams) {
108  memcpy(ogg->streams, ost->streams,
109  ost->nstreams * sizeof(*ogg->streams));
110  } else {
111  av_free(old_streams);
112  ogg->nstreams = 0;
113  }
114  }
115 
116  av_free(ost);
117 
118  return 0;
119 }
120 
121 static int ogg_reset(struct ogg *ogg)
122 {
123  int i;
124 
125  for (i = 0; i < ogg->nstreams; i++) {
126  struct ogg_stream *os = ogg->streams + i;
127  os->bufpos = 0;
128  os->pstart = 0;
129  os->psize = 0;
130  os->granule = -1;
131  os->lastpts = AV_NOPTS_VALUE;
132  os->lastdts = AV_NOPTS_VALUE;
133  os->sync_pos = -1;
134  os->page_pos = 0;
135  os->nsegs = 0;
136  os->segp = 0;
137  os->incomplete = 0;
138  }
139 
140  ogg->curidx = -1;
141 
142  return 0;
143 }
144 
145 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
146 {
147  int i;
148 
149  for (i = 0; ogg_codecs[i]; i++)
150  if (size >= ogg_codecs[i]->magicsize &&
151  !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
152  return ogg_codecs[i];
153 
154  return NULL;
155 }
156 
157 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
158 {
159  struct ogg *ogg = s->priv_data;
160  int idx = ogg->nstreams++;
161  AVStream *st;
162  struct ogg_stream *os;
163 
164  os = av_realloc(ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
165 
166  if (!os)
167  return AVERROR(ENOMEM);
168 
169  ogg->streams = os;
170 
171  memset(ogg->streams + idx, 0, sizeof(*ogg->streams));
172 
173  os = ogg->streams + idx;
174  os->serial = serial;
177  os->header = -1;
179 
180  if (new_avstream) {
181  st = avformat_new_stream(s, NULL);
182  if (!st)
183  return AVERROR(ENOMEM);
184 
185  st->id = idx;
186  avpriv_set_pts_info(st, 64, 1, 1000000);
187  }
188 
189  return idx;
190 }
191 
192 static int ogg_new_buf(struct ogg *ogg, int idx)
193 {
194  struct ogg_stream *os = ogg->streams + idx;
196  int size = os->bufpos - os->pstart;
197 
198  if (os->buf) {
199  memcpy(nb, os->buf + os->pstart, size);
200  av_free(os->buf);
201  }
202 
203  os->buf = nb;
204  os->bufpos = size;
205  os->pstart = 0;
206 
207  return 0;
208 }
209 
210 static int ogg_read_page(AVFormatContext *s, int *str)
211 {
212  AVIOContext *bc = s->pb;
213  struct ogg *ogg = s->priv_data;
214  struct ogg_stream *os;
215  int ret, i = 0;
216  int flags, nsegs;
217  uint64_t gp;
218  uint32_t serial;
219  int size, idx;
220  uint8_t sync[4];
221  int sp = 0;
222 
223  ret = avio_read(bc, sync, 4);
224  if (ret < 4)
225  return ret < 0 ? ret : AVERROR_EOF;
226 
227  do {
228  int c;
229 
230  if (sync[sp & 3] == 'O' &&
231  sync[(sp + 1) & 3] == 'g' &&
232  sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
233  break;
234 
235  c = avio_r8(bc);
236 
237  if (bc->eof_reached)
238  return AVERROR_EOF;
239 
240  sync[sp++ & 3] = c;
241  } while (i++ < MAX_PAGE_SIZE);
242 
243  if (i >= MAX_PAGE_SIZE) {
244  av_log(s, AV_LOG_INFO, "cannot find sync word\n");
245  return AVERROR_INVALIDDATA;
246  }
247 
248  if (avio_r8(bc) != 0) /* version */
249  return AVERROR_INVALIDDATA;
250 
251  flags = avio_r8(bc);
252  gp = avio_rl64(bc);
253  serial = avio_rl32(bc);
254  avio_skip(bc, 8); /* seq, crc */
255  nsegs = avio_r8(bc);
256 
257  idx = ogg_find_stream(ogg, serial);
258  if (idx < 0) {
259  if (ogg->headers) {
260  int n;
261 
262  for (n = 0; n < ogg->nstreams; n++) {
263  av_freep(&ogg->streams[n].buf);
264  if (!ogg->state ||
265  ogg->state->streams[n].private != ogg->streams[n].private)
266  av_freep(&ogg->streams[n].private);
267  }
268 
269  ogg->curidx = -1;
270  ogg->nstreams = 0;
271 
272  idx = ogg_new_stream(s, serial, 0);
273  } else {
274  idx = ogg_new_stream(s, serial, 1);
275  }
276  if (idx < 0)
277  return idx;
278  }
279 
280  os = ogg->streams + idx;
281  os->page_pos = avio_tell(bc) - 27;
282 
283  if (os->psize > 0)
284  ogg_new_buf(ogg, idx);
285 
286  ret = avio_read(bc, os->segments, nsegs);
287  if (ret < nsegs)
288  return ret < 0 ? ret : AVERROR_EOF;
289 
290  os->nsegs = nsegs;
291  os->segp = 0;
292 
293  size = 0;
294  for (i = 0; i < nsegs; i++)
295  size += os->segments[i];
296 
297  if (flags & OGG_FLAG_CONT || os->incomplete) {
298  if (!os->psize) {
299  while (os->segp < os->nsegs) {
300  int seg = os->segments[os->segp++];
301  os->pstart += seg;
302  if (seg < 255)
303  break;
304  }
305  os->sync_pos = os->page_pos;
306  }
307  } else {
308  os->psize = 0;
309  os->sync_pos = os->page_pos;
310  }
311 
312  if (os->bufsize - os->bufpos < size) {
314  if (!nb)
315  return AVERROR(ENOMEM);
316  memcpy(nb, os->buf, os->bufpos);
317  av_free(os->buf);
318  os->buf = nb;
319  }
320 
321  ret = avio_read(bc, os->buf + os->bufpos, size);
322  if (ret < size)
323  return ret < 0 ? ret : AVERROR_EOF;
324 
325  os->bufpos += size;
326  os->granule = gp;
327  os->flags = flags;
328 
329  memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
330  if (str)
331  *str = idx;
332 
333  return 0;
334 }
335 
336 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
337  int64_t *fpos)
338 {
339  struct ogg *ogg = s->priv_data;
340  int idx, i, ret;
341  struct ogg_stream *os;
342  int complete = 0;
343  int segp = 0, psize = 0;
344 
345  av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
346 
347  do {
348  idx = ogg->curidx;
349 
350  while (idx < 0) {
351  ret = ogg_read_page(s, &idx);
352  if (ret < 0)
353  return ret;
354  }
355 
356  os = ogg->streams + idx;
357 
358  av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
359  idx, os->pstart, os->psize, os->segp, os->nsegs);
360 
361  if (!os->codec) {
362  if (os->header < 0) {
363  os->codec = ogg_find_codec(os->buf, os->bufpos);
364  if (!os->codec) {
365  av_log(s, AV_LOG_WARNING, "Codec not found\n");
366  os->header = 0;
367  return 0;
368  }
369  } else {
370  return 0;
371  }
372  }
373 
374  segp = os->segp;
375  psize = os->psize;
376 
377  while (os->segp < os->nsegs) {
378  int ss = os->segments[os->segp++];
379  os->psize += ss;
380  if (ss < 255) {
381  complete = 1;
382  break;
383  }
384  }
385 
386  if (!complete && os->segp == os->nsegs) {
387  ogg->curidx = -1;
388  // Do not set incomplete for empty packets.
389  // Together with the code in ogg_read_page
390  // that discards all continuation of empty packets
391  // we would get an infinite loop.
392  os->incomplete = !!os->psize;
393  }
394  } while (!complete);
395 
396  av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
397  idx, os->psize, os->pstart);
398 
399  if (os->granule == -1)
401  "Page at %"PRId64" is missing granule\n",
402  os->page_pos);
403 
404  ogg->curidx = idx;
405  os->incomplete = 0;
406 
407  if (os->header) {
408  os->header = os->codec->header(s, idx);
409  if (!os->header) {
410  os->segp = segp;
411  os->psize = psize;
412 
413  // We have reached the first non-header packet in this stream.
414  // Unfortunately more header packets may still follow for others,
415  // but if we continue with header parsing we may lose data packets.
416  ogg->headers = 1;
417 
418  // Update the header state for all streams and
419  // compute the data_offset.
420  if (!s->data_offset)
421  s->data_offset = os->sync_pos;
422 
423  for (i = 0; i < ogg->nstreams; i++) {
424  struct ogg_stream *cur_os = ogg->streams + i;
425 
426  // if we have a partial non-header packet, its start is
427  // obviously at or after the data start
428  if (cur_os->incomplete)
429  s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
430  }
431  } else {
432  os->nb_header++;
433  os->pstart += os->psize;
434  os->psize = 0;
435  }
436  } else {
437  os->pflags = 0;
438  os->pduration = 0;
439  if (os->codec && os->codec->packet)
440  os->codec->packet(s, idx);
441  if (str)
442  *str = idx;
443  if (dstart)
444  *dstart = os->pstart;
445  if (dsize)
446  *dsize = os->psize;
447  if (fpos)
448  *fpos = os->sync_pos;
449  os->pstart += os->psize;
450  os->psize = 0;
451  os->sync_pos = os->page_pos;
452  }
453 
454  // determine whether there are more complete packets in this page
455  // if not, the page's granule will apply to this packet
456  os->page_end = 1;
457  for (i = os->segp; i < os->nsegs; i++)
458  if (os->segments[i] < 255) {
459  os->page_end = 0;
460  break;
461  }
462 
463  if (os->segp == os->nsegs)
464  ogg->curidx = -1;
465 
466  return 0;
467 }
468 
470 {
471  struct ogg *ogg = s->priv_data;
472  int ret, i;
473 
474  do {
475  ret = ogg_packet(s, NULL, NULL, NULL, NULL);
476  if (ret < 0)
477  return ret;
478  } while (!ogg->headers);
479 
480  for (i = 0; i < ogg->nstreams; i++) {
481  struct ogg_stream *os = ogg->streams + i;
482 
483  if (os->codec && os->codec->nb_header &&
484  os->nb_header < os->codec->nb_header) {
485  av_log(s, AV_LOG_ERROR,
486  "Headers mismatch for stream %d\n", i);
487  return AVERROR_INVALIDDATA;
488  }
490  os->lastpts = s->streams[i]->start_time =
491  ogg_gptopts(s, i, os->start_granule, NULL);
492  }
493  av_dlog(s, "found headers\n");
494 
495  return 0;
496 }
497 
499 {
500  struct ogg *ogg = s->priv_data;
501  int i;
502  int64_t size, end;
503 
504  if (!s->pb->seekable)
505  return 0;
506 
507 // already set
508  if (s->duration != AV_NOPTS_VALUE)
509  return 0;
510 
511  size = avio_size(s->pb);
512  if (size < 0)
513  return 0;
514  end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
515 
516  ogg_save(s);
517  avio_seek(s->pb, end, SEEK_SET);
518 
519  while (!ogg_read_page(s, &i)) {
520  if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
521  ogg->streams[i].codec) {
522  s->streams[i]->duration =
523  ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
524  if (s->streams[i]->start_time != AV_NOPTS_VALUE)
525  s->streams[i]->duration -= s->streams[i]->start_time;
526  }
527  }
528 
529  ogg_restore(s, 0);
530 
531  return 0;
532 }
533 
535 {
536  struct ogg *ogg = s->priv_data;
537  int i;
538 
539  for (i = 0; i < ogg->nstreams; i++) {
540  av_free(ogg->streams[i].buf);
541  if (ogg->streams[i].codec &&
542  ogg->streams[i].codec->cleanup) {
543  ogg->streams[i].codec->cleanup(s, i);
544  }
545  av_free(ogg->streams[i].private);
546  }
547  av_free(ogg->streams);
548  return 0;
549 }
550 
552 {
553  struct ogg *ogg = s->priv_data;
554  int ret, i;
555  ogg->curidx = -1;
556  //linear headers seek from start
557  ret = ogg_get_headers(s);
558  if (ret < 0) {
559  ogg_read_close(s);
560  return ret;
561  }
562 
563  for (i = 0; i < ogg->nstreams; i++)
564  if (ogg->streams[i].header < 0)
565  ogg->streams[i].codec = NULL;
566 
567  //linear granulepos seek from end
568  ogg_get_length(s);
569 
570  //fill the extradata in the per codec callbacks
571  return 0;
572 }
573 
574 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
575 {
576  struct ogg *ogg = s->priv_data;
577  struct ogg_stream *os = ogg->streams + idx;
578  int64_t pts = AV_NOPTS_VALUE;
579 
580  if (dts)
581  *dts = AV_NOPTS_VALUE;
582 
583  if (os->lastpts != AV_NOPTS_VALUE) {
584  pts = os->lastpts;
585  os->lastpts = AV_NOPTS_VALUE;
586  }
587  if (os->lastdts != AV_NOPTS_VALUE) {
588  if (dts)
589  *dts = os->lastdts;
590  os->lastdts = AV_NOPTS_VALUE;
591  }
592  if (os->page_end) {
593  if (os->granule != -1LL) {
594  if (os->codec && os->codec->granule_is_start)
595  pts = ogg_gptopts(s, idx, os->granule, dts);
596  else
597  os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
598  os->granule = -1LL;
599  }
600  }
601  return pts;
602 }
603 
605 {
606  struct ogg *ogg;
607  struct ogg_stream *os;
608  int idx = -1, ret;
609  int pstart, psize;
610  int64_t fpos, pts, dts;
611 
612  //Get an ogg packet
613 retry:
614  do {
615  ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
616  if (ret < 0)
617  return ret;
618  } while (idx < 0 || !s->streams[idx]);
619 
620  ogg = s->priv_data;
621  os = ogg->streams + idx;
622 
623  // pflags might not be set until after this
624  pts = ogg_calc_pts(s, idx, &dts);
625 
626  if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
627  goto retry;
628  os->keyframe_seek = 0;
629 
630  //Alloc a pkt
631  ret = av_new_packet(pkt, psize);
632  if (ret < 0)
633  return ret;
634  pkt->stream_index = idx;
635  memcpy(pkt->data, os->buf + pstart, psize);
636 
637  pkt->pts = pts;
638  pkt->dts = dts;
639  pkt->flags = os->pflags;
640  pkt->duration = os->pduration;
641  pkt->pos = fpos;
642 
643  return psize;
644 }
645 
646 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
647  int64_t *pos_arg, int64_t pos_limit)
648 {
649  struct ogg *ogg = s->priv_data;
650  AVIOContext *bc = s->pb;
651  int64_t pts = AV_NOPTS_VALUE;
652  int i = -1;
653  avio_seek(bc, *pos_arg, SEEK_SET);
654  ogg_reset(ogg);
655 
656  while (avio_tell(bc) < pos_limit &&
657  !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
658  if (i == stream_index) {
659  struct ogg_stream *os = ogg->streams + stream_index;
660  pts = ogg_calc_pts(s, i, NULL);
661  if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
662  pts = AV_NOPTS_VALUE;
663  }
664  if (pts != AV_NOPTS_VALUE)
665  break;
666  }
667  ogg_reset(ogg);
668  return pts;
669 }
670 
671 static int ogg_read_seek(AVFormatContext *s, int stream_index,
672  int64_t timestamp, int flags)
673 {
674  struct ogg *ogg = s->priv_data;
675  struct ogg_stream *os = ogg->streams + stream_index;
676  int ret;
677 
678  // Try seeking to a keyframe first. If this fails (very possible),
679  // av_seek_frame will fall back to ignoring keyframes
680  if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
681  && !(flags & AVSEEK_FLAG_ANY))
682  os->keyframe_seek = 1;
683 
684  ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
685  os = ogg->streams + stream_index;
686  if (ret < 0)
687  os->keyframe_seek = 0;
688  return ret;
689 }
690 
691 static int ogg_probe(AVProbeData *p)
692 {
693  if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
694  return AVPROBE_SCORE_MAX;
695  return 0;
696 }
697 
699  .name = "ogg",
700  .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
701  .priv_data_size = sizeof(struct ogg),
702  .read_probe = ogg_probe,
703  .read_header = ogg_read_header,
704  .read_packet = ogg_read_packet,
705  .read_close = ogg_read_close,
706  .read_seek = ogg_read_seek,
707  .read_timestamp = ogg_read_timestamp,
708  .extensions = "ogg",
709  .flags = AVFMT_GENERIC_INDEX,
710 };