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