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