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  av_freep(&ogg->streams[i].private);
705  } else if (os->codec && os->nb_header < os->codec->nb_header) {
707  "Headers mismatch for stream %d: "
708  "expected %d received %d.\n",
709  i, os->codec->nb_header, os->nb_header);
711  return AVERROR_INVALIDDATA;
712  }
714  os->lastpts = s->streams[i]->start_time =
715  ogg_gptopts(s, i, os->start_granule, NULL);
716  }
717 
718  //linear granulepos seek from end
719  ret = ogg_get_length(s);
720  if (ret < 0) {
721  ogg_read_close(s);
722  return ret;
723  }
724 
725  return 0;
726 }
727 
728 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
729 {
730  struct ogg *ogg = s->priv_data;
731  struct ogg_stream *os = ogg->streams + idx;
732  int64_t pts = AV_NOPTS_VALUE;
733 
734  if (dts)
735  *dts = AV_NOPTS_VALUE;
736 
737  if (os->lastpts != AV_NOPTS_VALUE) {
738  pts = os->lastpts;
739  os->lastpts = AV_NOPTS_VALUE;
740  }
741  if (os->lastdts != AV_NOPTS_VALUE) {
742  if (dts)
743  *dts = os->lastdts;
744  os->lastdts = AV_NOPTS_VALUE;
745  }
746  if (os->page_end) {
747  if (os->granule != -1LL) {
748  if (os->codec && os->codec->granule_is_start)
749  pts = ogg_gptopts(s, idx, os->granule, dts);
750  else
751  os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
752  os->granule = -1LL;
753  }
754  }
755  return pts;
756 }
757 
758 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
759 {
760  struct ogg *ogg = s->priv_data;
761  struct ogg_stream *os = ogg->streams + idx;
762  int invalid = 0;
763  if (psize) {
764  switch (s->streams[idx]->codecpar->codec_id) {
765  case AV_CODEC_ID_THEORA:
766  invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
767  break;
768  case AV_CODEC_ID_VP8:
769  invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
770  }
771  if (invalid) {
772  os->pflags ^= AV_PKT_FLAG_KEY;
773  av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
774  (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
775  }
776  }
777 }
778 
780 {
781  struct ogg *ogg;
782  struct ogg_stream *os;
783  int idx, ret;
784  int pstart, psize;
785  int64_t fpos, pts, dts;
786 
787  if (s->io_repositioned) {
788  ogg_reset(s);
789  s->io_repositioned = 0;
790  }
791 
792  //Get an ogg packet
793 retry:
794  do {
795  ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
796  if (ret < 0)
797  return ret;
798  } while (idx < 0 || !s->streams[idx]);
799 
800  ogg = s->priv_data;
801  os = ogg->streams + idx;
802 
803  // pflags might not be set until after this
804  pts = ogg_calc_pts(s, idx, &dts);
805  ogg_validate_keyframe(s, idx, pstart, psize);
806 
807  if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
808  goto retry;
809  os->keyframe_seek = 0;
810 
811  //Alloc a pkt
812  ret = av_new_packet(pkt, psize);
813  if (ret < 0)
814  return ret;
815  pkt->stream_index = idx;
816  memcpy(pkt->data, os->buf + pstart, psize);
817 
818  pkt->pts = pts;
819  pkt->dts = dts;
820  pkt->flags = os->pflags;
821  pkt->duration = os->pduration;
822  pkt->pos = fpos;
823 
824  if (os->end_trimming) {
825  uint8_t *side_data = av_packet_new_side_data(pkt,
827  10);
828  if(!side_data)
829  goto fail;
830  AV_WL32(side_data + 4, os->end_trimming);
831  os->end_trimming = 0;
832  }
833 
834  if (os->new_metadata) {
835  uint8_t *side_data = av_packet_new_side_data(pkt,
837  os->new_metadata_size);
838  if(!side_data)
839  goto fail;
840 
841  memcpy(side_data, os->new_metadata, os->new_metadata_size);
842  av_freep(&os->new_metadata);
843  os->new_metadata_size = 0;
844  }
845 
846  return psize;
847 fail:
848  av_packet_unref(pkt);
849  return AVERROR(ENOMEM);
850 }
851 
852 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
853  int64_t *pos_arg, int64_t pos_limit)
854 {
855  struct ogg *ogg = s->priv_data;
856  AVIOContext *bc = s->pb;
857  int64_t pts = AV_NOPTS_VALUE;
858  int64_t keypos = -1;
859  int i;
860  int pstart, psize;
861  avio_seek(bc, *pos_arg, SEEK_SET);
862  ogg_reset(s);
863 
864  while ( avio_tell(bc) <= pos_limit
865  && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
866  if (i == stream_index) {
867  struct ogg_stream *os = ogg->streams + stream_index;
868  // Do not trust the last timestamps of an ogm video
869  if ( (os->flags & OGG_FLAG_EOS)
870  && !(os->flags & OGG_FLAG_BOS)
871  && os->codec == &ff_ogm_video_codec)
872  continue;
873  pts = ogg_calc_pts(s, i, NULL);
874  ogg_validate_keyframe(s, i, pstart, psize);
875  if (os->pflags & AV_PKT_FLAG_KEY) {
876  keypos = *pos_arg;
877  } else if (os->keyframe_seek) {
878  // if we had a previous keyframe but no pts for it,
879  // return that keyframe with this pts value.
880  if (keypos >= 0)
881  *pos_arg = keypos;
882  else
883  pts = AV_NOPTS_VALUE;
884  }
885  }
886  if (pts != AV_NOPTS_VALUE)
887  break;
888  }
889  ogg_reset(s);
890  return pts;
891 }
892 
893 static int ogg_read_seek(AVFormatContext *s, int stream_index,
894  int64_t timestamp, int flags)
895 {
896  struct ogg *ogg = s->priv_data;
897  struct ogg_stream *os = ogg->streams + stream_index;
898  int ret;
899 
900  av_assert0(stream_index < ogg->nstreams);
901  // Ensure everything is reset even when seeking via
902  // the generated index.
903  ogg_reset(s);
904 
905  // Try seeking to a keyframe first. If this fails (very possible),
906  // av_seek_frame will fall back to ignoring keyframes
907  if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
908  && !(flags & AVSEEK_FLAG_ANY))
909  os->keyframe_seek = 1;
910 
911  ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
912  ogg_reset(s);
913  os = ogg->streams + stream_index;
914  if (ret < 0)
915  os->keyframe_seek = 0;
916  return ret;
917 }
918 
919 static int ogg_probe(AVProbeData *p)
920 {
921  if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
922  return AVPROBE_SCORE_MAX;
923  return 0;
924 }
925 
927  .name = "ogg",
928  .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
929  .priv_data_size = sizeof(struct ogg),
930  .read_probe = ogg_probe,
931  .read_header = ogg_read_header,
932  .read_packet = ogg_read_packet,
933  .read_close = ogg_read_close,
934  .read_seek = ogg_read_seek,
935  .read_timestamp = ogg_read_timestamp,
936  .extensions = "ogg",
938 };
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:490
const char * s
Definition: avisynth_c.h:631
Bytestream IO Context.
Definition: avio.h:147
#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:309
A list of zero terminated key/value strings.
Definition: avcodec.h:1505
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:1600
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:4427
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:2368
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:3922
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:230
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1752
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:304
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:919
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:779
const struct ogg_codec ff_ogm_old_codec
Definition: oggparseogm.c:213
Format I/O context.
Definition: avformat.h:1325
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:186
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:1598
int id
Format-specific stream ID.
Definition: avformat.h:883
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4065
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:1393
struct ogg_state * state
Definition: oggdec.h:107
uint8_t * data
Definition: avcodec.h:1580
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:511
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: oggdec.c:893
#define av_log(a,...)
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:598
const struct ogg_codec ff_skeleton_codec
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1612
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:486
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:720
#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
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3918
simple assert() macros that are a bit more flexible than ISO C assert().
const struct ogg_codec ff_opus_codec
Definition: oggparseopus.c:179
uint8_t segments[255]
Definition: oggdec.h:80
#define fail()
Definition: checkasm.h:81
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1586
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:589
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:461
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:243
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:728
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:926
#define AV_EF_EXPLODE
abort decoding on minor error detection
Definition: avcodec.h:2947
const struct ogg_codec ff_ogm_audio_codec
Definition: oggparseogm.c:195
Stream structure.
Definition: avformat.h:876
#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
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:1367
#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:458
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:563
int io_repositioned
IO repositioned flag.
Definition: avformat.h:1760
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:485
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:1452
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:459
const struct ogg_codec ff_old_flac_codec
Definition: oggparseflac.c:135
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:930
uint8_t * buf
Definition: oggdec.h:62
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:471
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:923
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:1566
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:204
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:731
#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:1353
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:758
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:1579
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, int64_t *pos_arg, int64_t pos_limit)
Definition: oggdec.c:852
int64_t duration
Duration of the stream, in AV_TIME_BASE fractional seconds.
Definition: avformat.h:1420
#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:660
int curidx
Definition: oggdec.h:105
AVCodecParameters * codecpar
Definition: avformat.h:1006
int avio_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:328
uint8_t * av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type, int size)
Allocate new information of a packet.
Definition: avpacket.c:313
int stream_index
Definition: avcodec.h:1582
struct ogg_stream streams[1]
Definition: oggdec.h:98
This structure stores compressed data.
Definition: avcodec.h:1557
uint64_t avio_rl64(AVIOContext *s)
Definition: aviobuf.c:728
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:1573
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:2014
#define AV_WL32(p, v)
Definition: intreadwrite.h:426