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 #include <stdio.h>
32 #include "libavutil/avassert.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 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
60 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
61 
62 //FIXME We could avoid some structure duplication
63 static int ogg_save(AVFormatContext *s)
64 {
65  struct ogg *ogg = s->priv_data;
66  struct ogg_state *ost =
67  av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
68  int i;
69  ost->pos = avio_tell(s->pb);
70  ost->curidx = ogg->curidx;
71  ost->next = ogg->state;
72  ost->nstreams = ogg->nstreams;
73  memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
74 
75  for (i = 0; i < ogg->nstreams; i++) {
76  struct ogg_stream *os = ogg->streams + i;
78  memcpy(os->buf, ost->streams[i].buf, os->bufpos);
79  }
80 
81  ogg->state = ost;
82 
83  return 0;
84 }
85 
86 static int ogg_restore(AVFormatContext *s, int discard)
87 {
88  struct ogg *ogg = s->priv_data;
89  AVIOContext *bc = s->pb;
90  struct ogg_state *ost = ogg->state;
91  int i;
92 
93  if (!ost)
94  return 0;
95 
96  ogg->state = ost->next;
97 
98  if (!discard) {
99  struct ogg_stream *old_streams = ogg->streams;
100 
101  for (i = 0; i < ogg->nstreams; i++)
102  av_free(ogg->streams[i].buf);
103 
104  avio_seek(bc, ost->pos, SEEK_SET);
105  ogg->page_pos = -1;
106  ogg->curidx = ost->curidx;
107  ogg->nstreams = ost->nstreams;
108  ogg->streams = av_realloc(ogg->streams,
109  ogg->nstreams * sizeof(*ogg->streams));
110 
111  if (ogg->streams) {
112  memcpy(ogg->streams, ost->streams,
113  ost->nstreams * sizeof(*ogg->streams));
114  } else {
115  av_free(old_streams);
116  ogg->nstreams = 0;
117  }
118  }
119 
120  av_free(ost);
121 
122  return 0;
123 }
124 
126 {
127  struct ogg *ogg = s->priv_data;
128  int i;
129  int64_t start_pos = avio_tell(s->pb);
130 
131  for (i = 0; i < ogg->nstreams; i++) {
132  struct ogg_stream *os = ogg->streams + i;
133  os->bufpos = 0;
134  os->pstart = 0;
135  os->psize = 0;
136  os->granule = -1;
137  os->lastpts = AV_NOPTS_VALUE;
138  os->lastdts = AV_NOPTS_VALUE;
139  os->sync_pos = -1;
140  os->page_pos = 0;
141  os->nsegs = 0;
142  os->segp = 0;
143  os->incomplete = 0;
144  os->got_data = 0;
145  if (start_pos <= s->data_offset) {
146  os->lastpts = 0;
147  }
148  }
149 
150  ogg->page_pos = -1;
151  ogg->curidx = -1;
152 
153  return 0;
154 }
155 
156 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
157 {
158  int i;
159 
160  for (i = 0; ogg_codecs[i]; i++)
161  if (size >= ogg_codecs[i]->magicsize &&
162  !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
163  return ogg_codecs[i];
164 
165  return NULL;
166 }
167 
168 /**
169  * Replace the current stream with a new one. This is a typical webradio
170  * situation where a new audio stream spawn (identified with a new serial) and
171  * must replace the previous one (track switch).
172  */
173 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
174 {
175  struct ogg *ogg = s->priv_data;
176  struct ogg_stream *os;
177  const struct ogg_codec *codec;
178  int i = 0;
179 
180  if (s->pb->seekable) {
181  uint8_t magic[8];
182  int64_t pos = avio_tell(s->pb);
183  avio_skip(s->pb, nsegs);
184  avio_read(s->pb, magic, sizeof(magic));
185  avio_seek(s->pb, pos, SEEK_SET);
186  codec = ogg_find_codec(magic, sizeof(magic));
187  if (!codec) {
188  av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
189  return AVERROR_INVALIDDATA;
190  }
191  for (i = 0; i < ogg->nstreams; i++) {
192  if (ogg->streams[i].codec == codec)
193  break;
194  }
195  if (i >= ogg->nstreams)
196  return ogg_new_stream(s, serial);
197  } else if (ogg->nstreams != 1) {
198  avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
199  return AVERROR_PATCHWELCOME;
200  }
201 
202  os = &ogg->streams[i];
203 
204  os->serial = serial;
205  return i;
206 
207 #if 0
208  buf = os->buf;
209  bufsize = os->bufsize;
210  codec = os->codec;
211 
212  if (!ogg->state || ogg->state->streams[i].private != os->private)
213  av_freep(&ogg->streams[i].private);
214 
215  /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
216  * also re-use the ogg_stream allocated buffer */
217  memset(os, 0, sizeof(*os));
218  os->serial = serial;
219  os->bufsize = bufsize;
220  os->buf = buf;
221  os->header = -1;
222  os->codec = codec;
223 
224  return i;
225 #endif
226 }
227 
228 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
229 {
230  struct ogg *ogg = s->priv_data;
231  int idx = ogg->nstreams;
232  AVStream *st;
233  struct ogg_stream *os;
234  size_t size;
235 
236  if (ogg->state) {
237  av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
238  "in between Ogg context save/restore operations.\n");
239  return AVERROR_BUG;
240  }
241 
242  /* Allocate and init a new Ogg Stream */
243  if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
244  !(os = av_realloc(ogg->streams, size)))
245  return AVERROR(ENOMEM);
246  ogg->streams = os;
247  os = ogg->streams + idx;
248  memset(os, 0, sizeof(*os));
249  os->serial = serial;
252  os->header = -1;
254  if (!os->buf)
255  return AVERROR(ENOMEM);
256 
257  /* Create the associated AVStream */
258  st = avformat_new_stream(s, NULL);
259  if (!st) {
260  av_freep(&os->buf);
261  return AVERROR(ENOMEM);
262  }
263  st->id = idx;
264  avpriv_set_pts_info(st, 64, 1, 1000000);
265 
266  ogg->nstreams++;
267  return idx;
268 }
269 
270 static int ogg_new_buf(struct ogg *ogg, int idx)
271 {
272  struct ogg_stream *os = ogg->streams + idx;
273  uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
274  int size = os->bufpos - os->pstart;
275 
276  if (os->buf) {
277  memcpy(nb, os->buf + os->pstart, size);
278  av_free(os->buf);
279  }
280 
281  os->buf = nb;
282  os->bufpos = size;
283  os->pstart = 0;
284 
285  return 0;
286 }
287 
288 static int data_packets_seen(const struct ogg *ogg)
289 {
290  int i;
291 
292  for (i = 0; i < ogg->nstreams; i++)
293  if (ogg->streams[i].got_data)
294  return 1;
295  return 0;
296 }
297 
298 static int ogg_read_page(AVFormatContext *s, int *sid)
299 {
300  AVIOContext *bc = s->pb;
301  struct ogg *ogg = s->priv_data;
302  struct ogg_stream *os;
303  int ret, i = 0;
304  int flags, nsegs;
305  uint64_t gp;
306  uint32_t serial;
307  int size, idx;
308  uint8_t sync[4];
309  int sp = 0;
310 
311  ret = avio_read(bc, sync, 4);
312  if (ret < 4)
313  return ret < 0 ? ret : AVERROR_EOF;
314 
315  do {
316  int c;
317 
318  if (sync[sp & 3] == 'O' &&
319  sync[(sp + 1) & 3] == 'g' &&
320  sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
321  break;
322 
323  if(!i && bc->seekable && ogg->page_pos > 0) {
324  memset(sync, 0, 4);
325  avio_seek(bc, ogg->page_pos+4, SEEK_SET);
326  ogg->page_pos = -1;
327  }
328 
329  c = avio_r8(bc);
330 
331  if (url_feof(bc))
332  return AVERROR_EOF;
333 
334  sync[sp++ & 3] = c;
335  } while (i++ < MAX_PAGE_SIZE);
336 
337  if (i >= MAX_PAGE_SIZE) {
338  av_log(s, AV_LOG_INFO, "cannot find sync word\n");
339  return AVERROR_INVALIDDATA;
340  }
341 
342  if (avio_r8(bc) != 0) { /* version */
343  av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
344  return AVERROR_INVALIDDATA;
345  }
346 
347  flags = avio_r8(bc);
348  gp = avio_rl64(bc);
349  serial = avio_rl32(bc);
350  avio_skip(bc, 8); /* seq, crc */
351  nsegs = avio_r8(bc);
352 
353  idx = ogg_find_stream(ogg, serial);
354  if (idx < 0) {
355  if (data_packets_seen(ogg))
356  idx = ogg_replace_stream(s, serial, nsegs);
357  else
358  idx = ogg_new_stream(s, serial);
359 
360  if (idx < 0) {
361  av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
362  return idx;
363  }
364  }
365 
366  os = ogg->streams + idx;
367  ogg->page_pos =
368  os->page_pos = avio_tell(bc) - 27;
369 
370  if (os->psize > 0)
371  ogg_new_buf(ogg, idx);
372 
373  ret = avio_read(bc, os->segments, nsegs);
374  if (ret < nsegs)
375  return ret < 0 ? ret : AVERROR_EOF;
376 
377  os->nsegs = nsegs;
378  os->segp = 0;
379 
380  size = 0;
381  for (i = 0; i < nsegs; i++)
382  size += os->segments[i];
383 
384  if (!(flags & OGG_FLAG_BOS))
385  os->got_data = 1;
386 
387  if (flags & OGG_FLAG_CONT || os->incomplete) {
388  if (!os->psize) {
389  // If this is the very first segment we started
390  // playback in the middle of a continuation packet.
391  // Discard it since we missed the start of it.
392  while (os->segp < os->nsegs) {
393  int seg = os->segments[os->segp++];
394  os->pstart += seg;
395  if (seg < 255)
396  break;
397  }
398  os->sync_pos = os->page_pos;
399  }
400  } else {
401  os->psize = 0;
402  os->sync_pos = os->page_pos;
403  }
404 
405  if (os->bufsize - os->bufpos < size) {
406  uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
407  if (!nb)
408  return AVERROR(ENOMEM);
409  memcpy(nb, os->buf, os->bufpos);
410  av_free(os->buf);
411  os->buf = nb;
412  }
413 
414  ret = avio_read(bc, os->buf + os->bufpos, size);
415  if (ret < size)
416  return ret < 0 ? ret : AVERROR_EOF;
417 
418  os->bufpos += size;
419  os->granule = gp;
420  os->flags = flags;
421 
422  memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
423  if (sid)
424  *sid = idx;
425 
426  return 0;
427 }
428 
429 /**
430  * @brief find the next Ogg packet
431  * @param *sid is set to the stream for the packet or -1 if there is
432  * no matching stream, in that case assume all other return
433  * values to be uninitialized.
434  * @return negative value on error or EOF.
435  */
436 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
437  int64_t *fpos)
438 {
439  struct ogg *ogg = s->priv_data;
440  int idx, i, ret;
441  struct ogg_stream *os;
442  int complete = 0;
443  int segp = 0, psize = 0;
444 
445  av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
446  if (sid)
447  *sid = -1;
448 
449  do {
450  idx = ogg->curidx;
451 
452  while (idx < 0) {
453  ret = ogg_read_page(s, &idx);
454  if (ret < 0)
455  return ret;
456  }
457 
458  os = ogg->streams + idx;
459 
460  av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
461  idx, os->pstart, os->psize, os->segp, os->nsegs);
462 
463  if (!os->codec) {
464  if (os->header < 0) {
465  os->codec = ogg_find_codec(os->buf, os->bufpos);
466  if (!os->codec) {
467  av_log(s, AV_LOG_WARNING, "Codec not found\n");
468  os->header = 0;
469  return 0;
470  }
471  } else {
472  return 0;
473  }
474  }
475 
476  segp = os->segp;
477  psize = os->psize;
478 
479  while (os->segp < os->nsegs) {
480  int ss = os->segments[os->segp++];
481  os->psize += ss;
482  if (ss < 255) {
483  complete = 1;
484  break;
485  }
486  }
487 
488  if (!complete && os->segp == os->nsegs) {
489  ogg->curidx = -1;
490  // Do not set incomplete for empty packets.
491  // Together with the code in ogg_read_page
492  // that discards all continuation of empty packets
493  // we would get an infinite loop.
494  os->incomplete = !!os->psize;
495  }
496  } while (!complete);
497 
498 
499  if (os->granule == -1)
501  "Page at %"PRId64" is missing granule\n",
502  os->page_pos);
503 
504  ogg->curidx = idx;
505  os->incomplete = 0;
506 
507  if (os->header) {
508  os->header = os->codec->header(s, idx);
509  if (!os->header) {
510  os->segp = segp;
511  os->psize = psize;
512 
513  // We have reached the first non-header packet in this stream.
514  // Unfortunately more header packets may still follow for others,
515  // but if we continue with header parsing we may lose data packets.
516  ogg->headers = 1;
517 
518  // Update the header state for all streams and
519  // compute the data_offset.
520  if (!s->data_offset)
521  s->data_offset = os->sync_pos;
522 
523  for (i = 0; i < ogg->nstreams; i++) {
524  struct ogg_stream *cur_os = ogg->streams + i;
525 
526  // if we have a partial non-header packet, its start is
527  // obviously at or after the data start
528  if (cur_os->incomplete)
529  s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
530  }
531  } else {
532  os->nb_header++;
533  os->pstart += os->psize;
534  os->psize = 0;
535  }
536  } else {
537  os->pflags = 0;
538  os->pduration = 0;
539  if (os->codec && os->codec->packet)
540  os->codec->packet(s, idx);
541  if (sid)
542  *sid = idx;
543  if (dstart)
544  *dstart = os->pstart;
545  if (dsize)
546  *dsize = os->psize;
547  if (fpos)
548  *fpos = os->sync_pos;
549  os->pstart += os->psize;
550  os->psize = 0;
551  if(os->pstart == os->bufpos)
552  os->bufpos = os->pstart = 0;
553  os->sync_pos = os->page_pos;
554  }
555 
556  // determine whether there are more complete packets in this page
557  // if not, the page's granule will apply to this packet
558  os->page_end = 1;
559  for (i = os->segp; i < os->nsegs; i++)
560  if (os->segments[i] < 255) {
561  os->page_end = 0;
562  break;
563  }
564 
565  if (os->segp == os->nsegs)
566  ogg->curidx = -1;
567 
568  return 0;
569 }
570 
572 {
573  struct ogg *ogg = s->priv_data;
574  int i;
575  int64_t size, end;
576  int streams_left=0;
577 
578  if (!s->pb->seekable)
579  return 0;
580 
581 // already set
582  if (s->duration != AV_NOPTS_VALUE)
583  return 0;
584 
585  size = avio_size(s->pb);
586  if (size < 0)
587  return 0;
588  end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
589 
590  ogg_save(s);
591  avio_seek(s->pb, end, SEEK_SET);
592  ogg->page_pos = -1;
593 
594  while (!ogg_read_page(s, &i)) {
595  if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
596  ogg->streams[i].codec) {
597  s->streams[i]->duration =
598  ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
599  if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
600  s->streams[i]->duration -= s->streams[i]->start_time;
601  streams_left-= (ogg->streams[i].got_start==-1);
602  ogg->streams[i].got_start= 1;
603  } else if(!ogg->streams[i].got_start) {
604  ogg->streams[i].got_start= -1;
605  streams_left++;
606  }
607  }
608  }
609 
610  ogg_restore(s, 0);
611 
612  ogg_save (s);
613  avio_seek (s->pb, s->data_offset, SEEK_SET);
614  ogg_reset(s);
615  while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
616  int64_t pts;
617  if (i < 0) continue;
618  pts = ogg_calc_pts(s, i, NULL);
619  if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
620  s->streams[i]->duration -= pts;
621  ogg->streams[i].got_start= 1;
622  streams_left--;
623  }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
624  ogg->streams[i].got_start= 1;
625  streams_left--;
626  }
627  }
628  ogg_restore (s, 0);
629 
630  return 0;
631 }
632 
634 {
635  struct ogg *ogg = s->priv_data;
636  int i;
637 
638  for (i = 0; i < ogg->nstreams; i++) {
639  av_free(ogg->streams[i].buf);
640  if (ogg->streams[i].codec &&
641  ogg->streams[i].codec->cleanup) {
642  ogg->streams[i].codec->cleanup(s, i);
643  }
644  av_free(ogg->streams[i].private);
645  }
646  av_free(ogg->streams);
647  return 0;
648 }
649 
651 {
652  struct ogg *ogg = s->priv_data;
653  int ret, i;
654 
655  ogg->curidx = -1;
656 
657  //linear headers seek from start
658  do {
659  ret = ogg_packet(s, NULL, NULL, NULL, NULL);
660  if (ret < 0) {
661  ogg_read_close(s);
662  return ret;
663  }
664  } while (!ogg->headers);
665  av_dlog(s, "found headers\n");
666 
667  for (i = 0; i < ogg->nstreams; i++) {
668  struct ogg_stream *os = ogg->streams + i;
669 
670  if (ogg->streams[i].header < 0) {
671  av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
672  ogg->streams[i].codec = NULL;
673  } else if (os->codec && os->nb_header < os->codec->nb_header) {
674  av_log(s, AV_LOG_WARNING, "Number of headers (%d) mismatch for stream %d\n", os->nb_header, i);
675  }
677  os->lastpts = s->streams[i]->start_time =
678  ogg_gptopts(s, i, os->start_granule, NULL);
679  }
680 
681  //linear granulepos seek from end
682  ogg_get_length(s);
683 
684  return 0;
685 }
686 
687 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
688 {
689  struct ogg *ogg = s->priv_data;
690  struct ogg_stream *os = ogg->streams + idx;
691  int64_t pts = AV_NOPTS_VALUE;
692 
693  if (dts)
694  *dts = AV_NOPTS_VALUE;
695 
696  if (os->lastpts != AV_NOPTS_VALUE) {
697  pts = os->lastpts;
698  os->lastpts = AV_NOPTS_VALUE;
699  }
700  if (os->lastdts != AV_NOPTS_VALUE) {
701  if (dts)
702  *dts = os->lastdts;
703  os->lastdts = AV_NOPTS_VALUE;
704  }
705  if (os->page_end) {
706  if (os->granule != -1LL) {
707  if (os->codec && os->codec->granule_is_start)
708  pts = ogg_gptopts(s, idx, os->granule, dts);
709  else
710  os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
711  os->granule = -1LL;
712  }
713  }
714  return pts;
715 }
716 
717 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
718 {
719  struct ogg *ogg = s->priv_data;
720  struct ogg_stream *os = ogg->streams + idx;
721  if (psize && s->streams[idx]->codec->codec_id == AV_CODEC_ID_THEORA) {
722  if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
723  os->pflags ^= AV_PKT_FLAG_KEY;
724  av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
725  (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
726  }
727  }
728 }
729 
731 {
732  struct ogg *ogg;
733  struct ogg_stream *os;
734  int idx, ret;
735  int pstart, psize;
736  int64_t fpos, pts, dts;
737 
738  if (s->io_repositioned) {
739  ogg_reset(s);
740  s->io_repositioned = 0;
741  }
742 
743  //Get an ogg packet
744 retry:
745  do {
746  ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
747  if (ret < 0)
748  return ret;
749  } while (idx < 0 || !s->streams[idx]);
750 
751  ogg = s->priv_data;
752  os = ogg->streams + idx;
753 
754  // pflags might not be set until after this
755  pts = ogg_calc_pts(s, idx, &dts);
756  ogg_validate_keyframe(s, idx, pstart, psize);
757 
758  if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
759  goto retry;
760  os->keyframe_seek = 0;
761 
762  //Alloc a pkt
763  ret = av_new_packet(pkt, psize);
764  if (ret < 0)
765  return ret;
766  pkt->stream_index = idx;
767  memcpy(pkt->data, os->buf + pstart, psize);
768 
769  pkt->pts = pts;
770  pkt->dts = dts;
771  pkt->flags = os->pflags;
772  pkt->duration = os->pduration;
773  pkt->pos = fpos;
774 
775  return psize;
776 }
777 
778 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
779  int64_t *pos_arg, int64_t pos_limit)
780 {
781  struct ogg *ogg = s->priv_data;
782  AVIOContext *bc = s->pb;
783  int64_t pts = AV_NOPTS_VALUE;
784  int64_t keypos = -1;
785  int i;
786  int pstart, psize;
787  avio_seek(bc, *pos_arg, SEEK_SET);
788  ogg_reset(s);
789 
790  while ( avio_tell(bc) <= pos_limit
791  && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
792  if (i == stream_index) {
793  struct ogg_stream *os = ogg->streams + stream_index;
794  pts = ogg_calc_pts(s, i, NULL);
795  ogg_validate_keyframe(s, i, pstart, psize);
796  if (os->pflags & AV_PKT_FLAG_KEY) {
797  keypos = *pos_arg;
798  } else if (os->keyframe_seek) {
799  // if we had a previous keyframe but no pts for it,
800  // return that keyframe with this pts value.
801  if (keypos >= 0)
802  *pos_arg = keypos;
803  else
804  pts = AV_NOPTS_VALUE;
805  }
806  }
807  if (pts != AV_NOPTS_VALUE)
808  break;
809  }
810  ogg_reset(s);
811  return pts;
812 }
813 
814 static int ogg_read_seek(AVFormatContext *s, int stream_index,
815  int64_t timestamp, int flags)
816 {
817  struct ogg *ogg = s->priv_data;
818  struct ogg_stream *os = ogg->streams + stream_index;
819  int ret;
820 
821  av_assert0(stream_index < ogg->nstreams);
822  // Ensure everything is reset even when seeking via
823  // the generated index.
824  ogg_reset(s);
825 
826  // Try seeking to a keyframe first. If this fails (very possible),
827  // av_seek_frame will fall back to ignoring keyframes
828  if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
829  && !(flags & AVSEEK_FLAG_ANY))
830  os->keyframe_seek = 1;
831 
832  ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
833  os = ogg->streams + stream_index;
834  if (ret < 0)
835  os->keyframe_seek = 0;
836  return ret;
837 }
838 
839 static int ogg_probe(AVProbeData *p)
840 {
841  if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
842  return AVPROBE_SCORE_MAX;
843  return 0;
844 }
845 
847  .name = "ogg",
848  .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
849  .priv_data_size = sizeof(struct ogg),
850  .read_probe = ogg_probe,
851  .read_header = ogg_read_header,
852  .read_packet = ogg_read_packet,
853  .read_close = ogg_read_close,
854  .read_seek = ogg_read_seek,
855  .read_timestamp = ogg_read_timestamp,
856  .extensions = "ogg",
858 };
int headers
Definition: oggdec.h:101
int header
Definition: oggdec.h:78
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
int granule_is_start
1 if granule is the start time of the associated packet.
Definition: oggdec.h:53
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:261
int size
int nstreams
Definition: oggdec.h:100
Copyright (C) 2005 Michael Ahlberg, Måns Rullgård.
Definition: oggdec.h:31
static const struct ogg_codec * ogg_find_codec(uint8_t *buf, int size)
Definition: oggdec.c:156
unsigned int bufsize
Definition: oggdec.h:63
unsigned int pflags
Definition: oggdec.h:67
const struct ogg_codec ff_celt_codec
Definition: oggparsecelt.c:92
#define DECODER_BUFFER_SIZE
Definition: oggdec.c:39
int nb_header
set to the number of parsed headers
Definition: oggdec.h:86
int(* packet)(AVFormatContext *, int)
Definition: oggdec.h:42
int64_t pos
byte position in stream, -1 if unknown
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
static int ogg_new_buf(struct ogg *ogg, int idx)
Definition: oggdec.c:270
#define OGG_NOGRANULE_VALUE
Definition: oggdec.h:111
void avpriv_report_missing_feature(void *avc, const char *msg,...)
Log a generic warning message about a missing feature.
Definition: log.c:306
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition: avformat.h:1745
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
const struct ogg_codec * codec
Definition: oggdec.h:77
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
static int sync(AVFormatContext *s, uint8_t *header)
Read input until we find the next ident.
Definition: lxfdec.c:85
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:256
int64_t data_offset
offset of the first packet
Definition: avformat.h:1242
int flags
Definition: oggdec.h:76
#define OGG_FLAG_CONT
Definition: oggdec.h:107
static int ogg_get_length(AVFormatContext *s)
Definition: oggdec.c:571
static int ogg_probe(AVProbeData *p)
Definition: oggdec.c:839
static const struct ogg_codec *const ogg_codecs[]
Definition: oggdec.c:41
int64_t lastpts
Definition: oggdec.h:72
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: oggdec.c:730
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
const struct ogg_codec ff_ogm_old_codec
Definition: oggparseogm.c:195
initialize output if(nPeaks >3)%at least 3 peaks in spectrum for trying to find f0 nf0peaks
Format I/O context.
Definition: avformat.h:944
unsigned int psize
Definition: oggdec.h:66
static int ogg_restore(AVFormatContext *s, int discard)
Definition: oggdec.c:86
int64_t sync_pos
file offset of the first page needed to reconstruct the current packet
Definition: oggdec.h:74
uint64_t pos
Definition: oggdec.h:91
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:141
const struct ogg_codec ff_ogm_video_codec
Definition: oggparseogm.c:168
static int data_packets_seen(const struct ogg *ogg)
Definition: oggdec.c:288
static AVPacket pkt
Definition: demuxing.c:56
int id
Format-specific stream ID.
Definition: avformat.h:650
end end
int(* header)(AVFormatContext *, int)
Attempt to process a packet as a header.
Definition: oggdec.h:41
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
int64_t page_pos
file offset of the current page
Definition: oggdec.h:75
AVStream ** streams
Definition: avformat.h:992
struct ogg_state * state
Definition: oggdec.h:104
uint8_t * data
int nstreams
Definition: oggdec.h:94
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define sp
Definition: regdef.h:63
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: oggdec.c:814
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
const struct ogg_codec ff_skeleton_codec
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
#define AVFMT_TS_DISCONT
Format allows timestamp discontinuities.
Definition: avformat.h:354
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:579
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
static int ogg_read_close(AVFormatContext *s)
Definition: oggdec.c:633
#define MAX_PAGE_SIZE
Definition: oggdec.c:38
simple assert() macros that are a bit more flexible than ISO C assert().
void av_log(void *avcl, int level, const char *fmt,...)
Send the specified message to the log if the level is less than or equal to the current av_log_level...
Definition: log.c:246
const struct ogg_codec ff_opus_codec
Definition: oggparseopus.c:129
uint8_t segments[255]
Definition: oggdec.h:80
int flags
A combination of AV_PKT_FLAG values.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int incomplete
whether we&#39;re expecting a continuation in the next page
Definition: oggdec.h:81
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:117
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
uint32_t serial
Definition: oggdec.h:69
#define FFMIN(a, b)
Definition: common.h:58
uint64_t granule
Definition: oggdec.h:70
static int ogg_read_page(AVFormatContext *s, int *sid)
Definition: oggdec.c:298
ret
Definition: avfilter.c:821
unsigned int pstart
Definition: oggdec.h:65
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
Definition: oggdec.c:687
static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
Replace the current stream with a new one.
Definition: oggdec.c:173
static int av_size_mult(size_t a, size_t b, size_t *r)
Multiply two size_t values checking for overflow.
Definition: mem.h:204
uint64_t start_granule
Definition: oggdec.h:71
struct ogg_stream * streams
Definition: oggdec.h:99
int segp
Definition: oggdec.h:79
const struct ogg_codec ff_vorbis_codec
#define OGG_FLAG_BOS
Definition: oggdec.h:108
int page_end
current packet is the last one completed in the page
Definition: oggdec.h:82
AVInputFormat ff_ogg_demuxer
Definition: oggdec.c:846
#define av_dlog(pctx,...)
av_dlog macros Useful to print debug messages that shouldn&#39;t get compiled in normally.
Definition: log.h:208
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
const struct ogg_codec ff_ogm_audio_codec
Definition: oggparseogm.c:177
Stream structure.
Definition: avformat.h:643
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:62
const struct ogg_codec ff_theora_codec
NULL
Definition: eval.c:55
static int ogg_find_stream(struct ogg *ogg, int serial)
Definition: oggdec.h:131
enum AVMediaType codec_type
unsigned int pduration
Definition: oggdec.h:68
int got_start
Definition: oggdec.h:84
int nsegs
Definition: oggdec.h:79
enum AVCodecID codec_id
AVIOContext * pb
I/O context.
Definition: avformat.h:977
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, int64_t *fpos)
find the next Ogg packet
Definition: oggdec.c:436
const struct ogg_codec ff_flac_codec
Definition: oggparseflac.c:88
const struct ogg_codec ff_old_dirac_codec
int io_repositioned
IO repositioned flag.
Definition: avformat.h:1269
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
void * private
Definition: oggdec.h:87
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:353
struct ogg_state * next
Definition: oggdec.h:93
synthesis window for stochastic i
static int ogg_read_header(AVFormatContext *s)
Definition: oggdec.c:650
int nb_header
Number of expected headers.
Definition: oggdec.h:57
static int ogg_reset(AVFormatContext *s)
Definition: oggdec.c:125
int64_t lastdts
Definition: oggdec.h:73
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
const struct ogg_codec ff_old_flac_codec
Definition: oggparseflac.c:95
void(* cleanup)(AVFormatContext *s, int idx)
Definition: oggdec.h:58
static int flags
Definition: cpu.c:23
int curidx
Definition: oggdec.h:92
const int8_t * magic
Definition: oggdec.h:32
const struct ogg_codec ff_dirac_codec
int64_t duration
Decoding: duration of the stream, in stream time base.
Definition: avformat.h:696
uint8_t * buf
Definition: oggdec.h:62
#define AVPROBE_SCORE_MAX
maximum score, half of that is used for file-extension-based detection
Definition: avformat.h:340
const struct ogg_codec ff_speex_codec
Main libavformat public API header.
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:689
static double c[64]
int got_data
1 if the stream got some data (non-initial packets), 0 otherwise
Definition: oggdec.h:85
const struct ogg_codec ff_ogm_text_codec
Definition: oggparseogm.c:186
int keyframe_seek
Definition: oggdec.h:83
Definition: oggdec.h:98
static int ogg_save(AVFormatContext *s)
Definition: oggdec.c:63
int64_t page_pos
file offset of the current page
Definition: oggdec.h:103
void * priv_data
Format private data.
Definition: avformat.h:964
static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
Definition: oggdec.c:228
static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
Definition: oggdec.c:717
uint8_t magicsize
Definition: oggdec.h:33
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit)
Definition: oggdec.c:778
int64_t duration
Decoding: duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1009
#define AV_LOG_INFO
Definition: log.h:156
#define gp
Definition: regdef.h:62
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
int curidx
Definition: oggdec.h:102
struct ogg_stream streams[1]
Definition: oggdec.h:95
This structure stores compressed data.
uint64_t avio_rl64(AVIOContext *s)
Definition: aviobuf.c:587
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
unsigned int bufpos
Definition: oggdec.h:64
static uint64_t ogg_gptopts(AVFormatContext *s, int i, uint64_t gp, int64_t *dts)
Definition: oggdec.h:143
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190
int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags)
Perform a binary search using av_index_search_timestamp() and AVInputFormat.read_timestamp().