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