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