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