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