FFmpeg  3.4.9
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  if (avio_read(s->pb, magic, sizeof(magic)) != sizeof(magic))
220  return AVERROR_INVALIDDATA;
221  avio_seek(s->pb, pos, SEEK_SET);
222  codec = ogg_find_codec(magic, sizeof(magic));
223  if (!codec) {
224  av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
225  return AVERROR_INVALIDDATA;
226  }
227  for (i = 0; i < ogg->nstreams; i++) {
228  if (ogg->streams[i].codec == codec)
229  break;
230  }
231  if (i >= ogg->nstreams)
232  return ogg_new_stream(s, serial);
233  } else if (ogg->nstreams != 1) {
234  avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
235  return AVERROR_PATCHWELCOME;
236  }
237 
238  os = &ogg->streams[i];
239 
240  os->serial = serial;
241  return i;
242 
243 #if 0
244  buf = os->buf;
245  bufsize = os->bufsize;
246  codec = os->codec;
247 
248  if (!ogg->state || ogg->state->streams[i].private != os->private)
249  av_freep(&ogg->streams[i].private);
250 
251  /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
252  * also re-use the ogg_stream allocated buffer */
253  memset(os, 0, sizeof(*os));
254  os->serial = serial;
255  os->bufsize = bufsize;
256  os->buf = buf;
257  os->header = -1;
258  os->codec = codec;
259 
260  return i;
261 #endif
262 }
263 
264 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
265 {
266  struct ogg *ogg = s->priv_data;
267  int idx = ogg->nstreams;
268  AVStream *st;
269  struct ogg_stream *os;
270  size_t size;
271 
272  if (ogg->state) {
273  av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
274  "in between Ogg context save/restore operations.\n");
275  return AVERROR_BUG;
276  }
277 
278  /* Allocate and init a new Ogg Stream */
279  if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
280  !(os = av_realloc(ogg->streams, size)))
281  return AVERROR(ENOMEM);
282  ogg->streams = os;
283  os = ogg->streams + idx;
284  memset(os, 0, sizeof(*os));
285  os->serial = serial;
288  os->header = -1;
290  if (!os->buf)
291  return AVERROR(ENOMEM);
292 
293  /* Create the associated AVStream */
294  st = avformat_new_stream(s, NULL);
295  if (!st) {
296  av_freep(&os->buf);
297  return AVERROR(ENOMEM);
298  }
299  st->id = idx;
300  avpriv_set_pts_info(st, 64, 1, 1000000);
301 
302  ogg->nstreams++;
303  return idx;
304 }
305 
306 static int ogg_new_buf(struct ogg *ogg, int idx)
307 {
308  struct ogg_stream *os = ogg->streams + idx;
310  int size = os->bufpos - os->pstart;
311 
312  if (!nb)
313  return AVERROR(ENOMEM);
314 
315  if (os->buf) {
316  memcpy(nb, os->buf + os->pstart, size);
317  av_free(os->buf);
318  }
319 
320  os->buf = nb;
321  os->bufpos = size;
322  os->pstart = 0;
323 
324  return 0;
325 }
326 
327 static int data_packets_seen(const struct ogg *ogg)
328 {
329  int i;
330 
331  for (i = 0; i < ogg->nstreams; i++)
332  if (ogg->streams[i].got_data)
333  return 1;
334  return 0;
335 }
336 
337 static int ogg_read_page(AVFormatContext *s, int *sid)
338 {
339  AVIOContext *bc = s->pb;
340  struct ogg *ogg = s->priv_data;
341  struct ogg_stream *os;
342  int ret, i = 0;
343  int flags, nsegs;
344  uint64_t gp;
345  uint32_t serial;
346  int size, idx;
347  uint8_t sync[4];
348  int sp = 0;
349 
350  ret = avio_read(bc, sync, 4);
351  if (ret < 4)
352  return ret < 0 ? ret : AVERROR_EOF;
353 
354  do {
355  int c;
356 
357  if (sync[sp & 3] == 'O' &&
358  sync[(sp + 1) & 3] == 'g' &&
359  sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
360  break;
361 
362  if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
363  memset(sync, 0, 4);
364  avio_seek(bc, ogg->page_pos+4, SEEK_SET);
365  ogg->page_pos = -1;
366  }
367 
368  c = avio_r8(bc);
369 
370  if (avio_feof(bc))
371  return AVERROR_EOF;
372 
373  sync[sp++ & 3] = c;
374  } while (i++ < MAX_PAGE_SIZE);
375 
376  if (i >= MAX_PAGE_SIZE) {
377  av_log(s, AV_LOG_INFO, "cannot find sync word\n");
378  return AVERROR_INVALIDDATA;
379  }
380 
381  if (avio_r8(bc) != 0) { /* version */
382  av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
383  return AVERROR_INVALIDDATA;
384  }
385 
386  flags = avio_r8(bc);
387  gp = avio_rl64(bc);
388  serial = avio_rl32(bc);
389  avio_skip(bc, 8); /* seq, crc */
390  nsegs = avio_r8(bc);
391 
392  if (avio_feof(bc))
393  return AVERROR_EOF;
394 
395  idx = ogg_find_stream(ogg, serial);
396  if (idx < 0) {
397  if (data_packets_seen(ogg))
398  idx = ogg_replace_stream(s, serial, nsegs);
399  else
400  idx = ogg_new_stream(s, serial);
401 
402  if (idx < 0) {
403  av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
404  return idx;
405  }
406  }
407 
408  os = ogg->streams + idx;
409  ogg->page_pos =
410  os->page_pos = avio_tell(bc) - 27;
411 
412  if (os->psize > 0) {
413  ret = ogg_new_buf(ogg, idx);
414  if (ret < 0)
415  return ret;
416  }
417 
418  ret = avio_read(bc, os->segments, nsegs);
419  if (ret < nsegs)
420  return ret < 0 ? ret : AVERROR_EOF;
421 
422  os->nsegs = nsegs;
423  os->segp = 0;
424 
425  size = 0;
426  for (i = 0; i < nsegs; i++)
427  size += os->segments[i];
428 
429  if (!(flags & OGG_FLAG_BOS))
430  os->got_data = 1;
431 
432  if (flags & OGG_FLAG_CONT || os->incomplete) {
433  if (!os->psize) {
434  // If this is the very first segment we started
435  // playback in the middle of a continuation packet.
436  // Discard it since we missed the start of it.
437  while (os->segp < os->nsegs) {
438  int seg = os->segments[os->segp++];
439  os->pstart += seg;
440  if (seg < 255)
441  break;
442  }
443  os->sync_pos = os->page_pos;
444  }
445  } else {
446  os->psize = 0;
447  os->sync_pos = os->page_pos;
448  }
449 
450  if (os->bufsize - os->bufpos < size) {
452  if (!nb)
453  return AVERROR(ENOMEM);
454  memcpy(nb, os->buf, os->bufpos);
455  av_free(os->buf);
456  os->buf = nb;
457  }
458 
459  ret = avio_read(bc, os->buf + os->bufpos, size);
460  if (ret < size)
461  return ret < 0 ? ret : AVERROR_EOF;
462 
463  os->bufpos += size;
464  os->granule = gp;
465  os->flags = flags;
466 
467  memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
468  if (sid)
469  *sid = idx;
470 
471  return 0;
472 }
473 
474 /**
475  * @brief find the next Ogg packet
476  * @param *sid is set to the stream for the packet or -1 if there is
477  * no matching stream, in that case assume all other return
478  * values to be uninitialized.
479  * @return negative value on error or EOF.
480  */
481 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
482  int64_t *fpos)
483 {
484  struct ogg *ogg = s->priv_data;
485  int idx, i, ret;
486  struct ogg_stream *os;
487  int complete = 0;
488  int segp = 0, psize = 0;
489 
490  av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
491  if (sid)
492  *sid = -1;
493 
494  do {
495  idx = ogg->curidx;
496 
497  while (idx < 0) {
498  ret = ogg_read_page(s, &idx);
499  if (ret < 0)
500  return ret;
501  }
502 
503  os = ogg->streams + idx;
504 
505  av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
506  idx, os->pstart, os->psize, os->segp, os->nsegs);
507 
508  if (!os->codec) {
509  if (os->header < 0) {
510  os->codec = ogg_find_codec(os->buf, os->bufpos);
511  if (!os->codec) {
512  av_log(s, AV_LOG_WARNING, "Codec not found\n");
513  os->header = 0;
514  return 0;
515  }
516  } else {
517  return 0;
518  }
519  }
520 
521  segp = os->segp;
522  psize = os->psize;
523 
524  while (os->segp < os->nsegs) {
525  int ss = os->segments[os->segp++];
526  os->psize += ss;
527  if (ss < 255) {
528  complete = 1;
529  break;
530  }
531  }
532 
533  if (!complete && os->segp == os->nsegs) {
534  ogg->curidx = -1;
535  // Do not set incomplete for empty packets.
536  // Together with the code in ogg_read_page
537  // that discards all continuation of empty packets
538  // we would get an infinite loop.
539  os->incomplete = !!os->psize;
540  }
541  } while (!complete);
542 
543 
544  if (os->granule == -1)
546  "Page at %"PRId64" is missing granule\n",
547  os->page_pos);
548 
549  ogg->curidx = idx;
550  os->incomplete = 0;
551 
552  if (os->header) {
553  os->header = os->codec->header(s, idx);
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  os->codec->packet(s, idx);
586  if (sid)
587  *sid = idx;
588  if (dstart)
589  *dstart = os->pstart;
590  if (dsize)
591  *dsize = os->psize;
592  if (fpos)
593  *fpos = os->sync_pos;
594  os->pstart += os->psize;
595  os->psize = 0;
596  if(os->pstart == os->bufpos)
597  os->bufpos = os->pstart = 0;
598  os->sync_pos = os->page_pos;
599  }
600 
601  // determine whether there are more complete packets in this page
602  // if not, the page's granule will apply to this packet
603  os->page_end = 1;
604  for (i = os->segp; i < os->nsegs; i++)
605  if (os->segments[i] < 255) {
606  os->page_end = 0;
607  break;
608  }
609 
610  if (os->segp == os->nsegs)
611  ogg->curidx = -1;
612 
613  return 0;
614 }
615 
617 {
618  struct ogg *ogg = s->priv_data;
619  int i, ret;
620  int64_t size, end;
621  int streams_left=0;
622 
623  if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
624  return 0;
625 
626 // already set
627  if (s->duration != AV_NOPTS_VALUE)
628  return 0;
629 
630  size = avio_size(s->pb);
631  if (size < 0)
632  return 0;
633  end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
634 
635  ret = ogg_save(s);
636  if (ret < 0)
637  return ret;
638  avio_seek(s->pb, end, SEEK_SET);
639  ogg->page_pos = -1;
640 
641  while (!ogg_read_page(s, &i)) {
642  if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
643  ogg->streams[i].codec) {
644  s->streams[i]->duration =
645  ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
646  if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
647  s->streams[i]->duration -= s->streams[i]->start_time;
648  streams_left-= (ogg->streams[i].got_start==-1);
649  ogg->streams[i].got_start= 1;
650  } else if(!ogg->streams[i].got_start) {
651  ogg->streams[i].got_start= -1;
652  streams_left++;
653  }
654  }
655  }
656 
657  ogg_restore(s);
658 
659  ret = ogg_save(s);
660  if (ret < 0)
661  return ret;
662 
663  avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
664  ogg_reset(s);
665  while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
666  int64_t pts;
667  if (i < 0) continue;
668  pts = ogg_calc_pts(s, i, NULL);
669  if (s->streams[i]->duration == AV_NOPTS_VALUE)
670  continue;
671  if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
672  s->streams[i]->duration -= pts;
673  ogg->streams[i].got_start= 1;
674  streams_left--;
675  }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
676  ogg->streams[i].got_start= 1;
677  streams_left--;
678  }
679  }
680  ogg_restore (s);
681 
682  return 0;
683 }
684 
686 {
687  struct ogg *ogg = s->priv_data;
688  int i;
689 
690  for (i = 0; i < ogg->nstreams; i++) {
691  free_stream(s, i);
692  }
693 
694  ogg->nstreams = 0;
695 
696  av_freep(&ogg->streams);
697  return 0;
698 }
699 
701 {
702  struct ogg *ogg = s->priv_data;
703  int ret, i;
704 
705  ogg->curidx = -1;
706 
707  //linear headers seek from start
708  do {
709  ret = ogg_packet(s, NULL, NULL, NULL, NULL);
710  if (ret < 0) {
711  ogg_read_close(s);
712  return ret;
713  }
714  } while (!ogg->headers);
715  av_log(s, AV_LOG_TRACE, "found headers\n");
716 
717  for (i = 0; i < ogg->nstreams; i++) {
718  struct ogg_stream *os = ogg->streams + i;
719 
720  if (ogg->streams[i].header < 0) {
721  av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
722  ogg->streams[i].codec = NULL;
723  av_freep(&ogg->streams[i].private);
724  } else if (os->codec && os->nb_header < os->codec->nb_header) {
726  "Headers mismatch for stream %d: "
727  "expected %d received %d.\n",
728  i, os->codec->nb_header, os->nb_header);
729  if (s->error_recognition & AV_EF_EXPLODE) {
730  ogg_read_close(s);
731  return AVERROR_INVALIDDATA;
732  }
733  }
735  os->lastpts = s->streams[i]->start_time =
736  ogg_gptopts(s, i, os->start_granule, NULL);
737  }
738 
739  //linear granulepos seek from end
740  ret = ogg_get_length(s);
741  if (ret < 0) {
742  ogg_read_close(s);
743  return ret;
744  }
745 
746  return 0;
747 }
748 
749 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
750 {
751  struct ogg *ogg = s->priv_data;
752  struct ogg_stream *os = ogg->streams + idx;
753  int64_t pts = AV_NOPTS_VALUE;
754 
755  if (dts)
756  *dts = AV_NOPTS_VALUE;
757 
758  if (os->lastpts != AV_NOPTS_VALUE) {
759  pts = os->lastpts;
760  os->lastpts = AV_NOPTS_VALUE;
761  }
762  if (os->lastdts != AV_NOPTS_VALUE) {
763  if (dts)
764  *dts = os->lastdts;
765  os->lastdts = AV_NOPTS_VALUE;
766  }
767  if (os->page_end) {
768  if (os->granule != -1LL) {
769  if (os->codec && os->codec->granule_is_start)
770  pts = ogg_gptopts(s, idx, os->granule, dts);
771  else
772  os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
773  os->granule = -1LL;
774  }
775  }
776  return pts;
777 }
778 
779 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
780 {
781  struct ogg *ogg = s->priv_data;
782  struct ogg_stream *os = ogg->streams + idx;
783  int invalid = 0;
784  if (psize) {
785  switch (s->streams[idx]->codecpar->codec_id) {
786  case AV_CODEC_ID_THEORA:
787  invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
788  break;
789  case AV_CODEC_ID_VP8:
790  invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
791  }
792  if (invalid) {
793  os->pflags ^= AV_PKT_FLAG_KEY;
794  av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
795  (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
796  }
797  }
798 }
799 
801 {
802  struct ogg *ogg;
803  struct ogg_stream *os;
804  int idx, ret;
805  int pstart, psize;
806  int64_t fpos, pts, dts;
807 
808  if (s->io_repositioned) {
809  ogg_reset(s);
810  s->io_repositioned = 0;
811  }
812 
813  //Get an ogg packet
814 retry:
815  do {
816  ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
817  if (ret < 0)
818  return ret;
819  } while (idx < 0 || !s->streams[idx]);
820 
821  ogg = s->priv_data;
822  os = ogg->streams + idx;
823 
824  // pflags might not be set until after this
825  pts = ogg_calc_pts(s, idx, &dts);
826  ogg_validate_keyframe(s, idx, pstart, psize);
827 
828  if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
829  goto retry;
830  os->keyframe_seek = 0;
831 
832  //Alloc a pkt
833  ret = av_new_packet(pkt, psize);
834  if (ret < 0)
835  return ret;
836  pkt->stream_index = idx;
837  memcpy(pkt->data, os->buf + pstart, psize);
838 
839  pkt->pts = pts;
840  pkt->dts = dts;
841  pkt->flags = os->pflags;
842  pkt->duration = os->pduration;
843  pkt->pos = fpos;
844 
845  if (os->end_trimming) {
846  uint8_t *side_data = av_packet_new_side_data(pkt,
848  10);
849  if(!side_data)
850  goto fail;
851  AV_WL32(side_data + 4, os->end_trimming);
852  os->end_trimming = 0;
853  }
854 
855  if (os->new_metadata) {
856  uint8_t *side_data = av_packet_new_side_data(pkt,
858  os->new_metadata_size);
859  if(!side_data)
860  goto fail;
861 
862  memcpy(side_data, os->new_metadata, os->new_metadata_size);
863  av_freep(&os->new_metadata);
864  os->new_metadata_size = 0;
865  }
866 
867  return psize;
868 fail:
869  av_packet_unref(pkt);
870  return AVERROR(ENOMEM);
871 }
872 
873 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
874  int64_t *pos_arg, int64_t pos_limit)
875 {
876  struct ogg *ogg = s->priv_data;
877  AVIOContext *bc = s->pb;
878  int64_t pts = AV_NOPTS_VALUE;
879  int64_t keypos = -1;
880  int i;
881  int pstart, psize;
882  avio_seek(bc, *pos_arg, SEEK_SET);
883  ogg_reset(s);
884 
885  while ( avio_tell(bc) <= pos_limit
886  && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
887  if (i == stream_index) {
888  struct ogg_stream *os = ogg->streams + stream_index;
889  // Do not trust the last timestamps of an ogm video
890  if ( (os->flags & OGG_FLAG_EOS)
891  && !(os->flags & OGG_FLAG_BOS)
892  && os->codec == &ff_ogm_video_codec)
893  continue;
894  pts = ogg_calc_pts(s, i, NULL);
895  ogg_validate_keyframe(s, i, pstart, psize);
896  if (os->pflags & AV_PKT_FLAG_KEY) {
897  keypos = *pos_arg;
898  } else if (os->keyframe_seek) {
899  // if we had a previous keyframe but no pts for it,
900  // return that keyframe with this pts value.
901  if (keypos >= 0)
902  *pos_arg = keypos;
903  else
904  pts = AV_NOPTS_VALUE;
905  }
906  }
907  if (pts != AV_NOPTS_VALUE)
908  break;
909  }
910  ogg_reset(s);
911  return pts;
912 }
913 
914 static int ogg_read_seek(AVFormatContext *s, int stream_index,
915  int64_t timestamp, int flags)
916 {
917  struct ogg *ogg = s->priv_data;
918  struct ogg_stream *os = ogg->streams + stream_index;
919  int ret;
920 
921  av_assert0(stream_index < ogg->nstreams);
922  // Ensure everything is reset even when seeking via
923  // the generated index.
924  ogg_reset(s);
925 
926  // Try seeking to a keyframe first. If this fails (very possible),
927  // av_seek_frame will fall back to ignoring keyframes
928  if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
929  && !(flags & AVSEEK_FLAG_ANY))
930  os->keyframe_seek = 1;
931 
932  ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
933  ogg_reset(s);
934  os = ogg->streams + stream_index;
935  if (ret < 0)
936  os->keyframe_seek = 0;
937  return ret;
938 }
939 
940 static int ogg_probe(AVProbeData *p)
941 {
942  if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
943  return AVPROBE_SCORE_MAX;
944  return 0;
945 }
946 
948  .name = "ogg",
949  .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
950  .priv_data_size = sizeof(struct ogg),
951  .read_probe = ogg_probe,
952  .read_header = ogg_read_header,
953  .read_packet = ogg_read_packet,
954  .read_close = ogg_read_close,
955  .read_seek = ogg_read_seek,
956  .read_timestamp = ogg_read_timestamp,
957  .extensions = "ogg",
959 };
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:492
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:334
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:1574
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:1699
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:4756
static int ogg_new_buf(struct ogg *ogg, int idx)
Definition: oggdec.c:306
#define OGG_NOGRANULE_VALUE
Definition: oggdec.h:114
#define AVSEEK_FLAG_ANY
seek to any frame, even non-keyframes
Definition: avformat.h:2425
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:4152
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:244
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1780
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:329
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:616
static int ogg_probe(AVProbeData *p)
Definition: oggdec.c:940
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:800
const struct ogg_codec ff_ogm_old_codec
Definition: oggparseogm.c:219
Format I/O context.
Definition: avformat.h:1349
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:192
static int data_packets_seen(const struct ogg *ogg)
Definition: oggdec.c:327
#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:1697
int id
Format-specific stream ID.
Definition: avformat.h:896
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:4383
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:1417
struct ogg_state * state
Definition: oggdec.h:107
uint8_t * data
Definition: avcodec.h:1679
static int flags
Definition: log.c:57
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:556
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: oggdec.c:914
#define av_log(a,...)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:636
const struct ogg_codec ff_skeleton_codec
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1711
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:488
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:758
#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:181
static int ogg_read_close(AVFormatContext *s)
Definition: oggdec.c:685
#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:4148
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:222
const struct ogg_codec ff_opus_codec
Definition: oggparseopus.c:179
uint8_t segments[255]
Definition: oggdec.h:80
#define fail()
Definition: checkasm.h:109
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1685
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:627
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:191
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:463
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:261
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:337
unsigned int pstart
Definition: oggdec.h:65
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
Definition: oggdec.c:749
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
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:947
#define AV_EF_EXPLODE
abort decoding on minor error detection
Definition: avcodec.h:3061
if(ret< 0)
Definition: vf_mcdeint.c:279
const struct ogg_codec ff_ogm_audio_codec
Definition: oggparseogm.c:201
Stream structure.
Definition: avformat.h:889
#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:1391
#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:481
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:618
int io_repositioned
IO repositioned flag.
Definition: avformat.h:1788
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:487
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:700
int nb_header
Number of expected headers.
Definition: oggdec.h:57
Recommmends skipping the specified number of samples.
Definition: avcodec.h:1521
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:461
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
Global timestamp for the audio frames.
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:946
uint8_t * buf
Definition: oggdec.h:62
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:473
const struct ogg_codec ff_speex_codec
Main libavformat public API header.
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:936
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:1594
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:668
const struct ogg_codec ff_ogm_text_codec
Definition: oggparseogm.c:210
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:777
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:1377
const struct ogg_codec ff_daala_codec
static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
Definition: oggdec.c:264
static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
Definition: oggdec.c:779
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:1678
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit)
Definition: oggdec.c:873
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1444
#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:664
int curidx
Definition: oggdec.h:105
AVCodecParameters * codecpar
Definition: avformat.h:1252
int avio_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:356
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:1681
struct ogg_stream streams[1]
Definition: oggdec.h:98
This structure stores compressed data.
Definition: avcodec.h:1656
uint64_t avio_rl64(AVIOContext *s)
Definition: aviobuf.c:766
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1672
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:2120
#define AV_WL32(p, v)
Definition: intreadwrite.h:431