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