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