• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "avio_internal.h"
35 #include "oggdec.h"
36 #include "avformat.h"
37 #include "internal.h"
38 #include "vorbiscomment.h"
39 
40 #define MAX_PAGE_SIZE 65307
41 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
42 
43 static const struct ogg_codec * const ogg_codecs[] = {
44     &ff_skeleton_codec,
45     &ff_dirac_codec,
46     &ff_speex_codec,
47     &ff_vorbis_codec,
48     &ff_theora_codec,
49     &ff_flac_codec,
50     &ff_celt_codec,
51     &ff_opus_codec,
52     &ff_vp8_codec,
53     &ff_old_dirac_codec,
54     &ff_old_flac_codec,
55     &ff_ogm_video_codec,
56     &ff_ogm_audio_codec,
57     &ff_ogm_text_codec,
58     &ff_ogm_old_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 
free_stream(AVFormatContext * s,int i)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
ogg_save(AVFormatContext * s)82 static int ogg_save(AVFormatContext *s)
83 {
84     struct ogg *ogg = s->priv_data;
85     struct ogg_state *ost =
86         av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
87     int i;
88     int ret = 0;
89 
90     if (!ost)
91         return AVERROR(ENOMEM);
92 
93     ost->pos      = avio_tell(s->pb);
94     ost->curidx   = ogg->curidx;
95     ost->next     = ogg->state;
96     ost->nstreams = ogg->nstreams;
97     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
98 
99     for (i = 0; i < ogg->nstreams; i++) {
100         struct ogg_stream *os = ogg->streams + i;
101         os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
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 
ogg_restore(AVFormatContext * s)118 static int ogg_restore(AVFormatContext *s)
119 {
120     struct ogg *ogg = s->priv_data;
121     AVIOContext *bc = s->pb;
122     struct ogg_state *ost = ogg->state;
123     int i, err;
124 
125     if (!ost)
126         return 0;
127 
128     ogg->state = ost->next;
129 
130         for (i = 0; i < ogg->nstreams; i++) {
131             struct ogg_stream *stream = &ogg->streams[i];
132             av_freep(&stream->buf);
133             av_freep(&stream->new_metadata);
134 
135             if (i >= ost->nstreams || !ost->streams[i].private) {
136                 free_stream(s, i);
137             }
138         }
139 
140         avio_seek(bc, ost->pos, SEEK_SET);
141         ogg->page_pos = -1;
142         ogg->curidx   = ost->curidx;
143         ogg->nstreams = ost->nstreams;
144         if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
145                                      sizeof(*ogg->streams))) < 0) {
146             ogg->nstreams = 0;
147             return err;
148         } else
149             memcpy(ogg->streams, ost->streams,
150                    ost->nstreams * sizeof(*ogg->streams));
151 
152     av_free(ost);
153 
154     return 0;
155 }
156 
ogg_reset(AVFormatContext * s)157 static int ogg_reset(AVFormatContext *s)
158 {
159     struct ogg *ogg = s->priv_data;
160     int i;
161     int64_t start_pos = avio_tell(s->pb);
162 
163     for (i = 0; i < ogg->nstreams; i++) {
164         struct ogg_stream *os = ogg->streams + i;
165         os->bufpos     = 0;
166         os->pstart     = 0;
167         os->psize      = 0;
168         os->granule    = -1;
169         os->lastpts    = AV_NOPTS_VALUE;
170         os->lastdts    = AV_NOPTS_VALUE;
171         os->sync_pos   = -1;
172         os->page_pos   = 0;
173         os->nsegs      = 0;
174         os->segp       = 0;
175         os->incomplete = 0;
176         os->got_data = 0;
177         if (start_pos <= s->internal->data_offset) {
178             os->lastpts = 0;
179         }
180         os->start_trimming = 0;
181         os->end_trimming = 0;
182         av_freep(&os->new_metadata);
183         os->new_metadata_size = 0;
184     }
185 
186     ogg->page_pos = -1;
187     ogg->curidx = -1;
188 
189     return 0;
190 }
191 
ogg_find_codec(uint8_t * buf,int size)192 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
193 {
194     int i;
195 
196     for (i = 0; ogg_codecs[i]; i++)
197         if (size >= ogg_codecs[i]->magicsize &&
198             !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
199             return ogg_codecs[i];
200 
201     return NULL;
202 }
203 
204 /**
205  * Replace the current stream with a new one. This is a typical webradio
206  * situation where a new audio stream spawn (identified with a new serial) and
207  * must replace the previous one (track switch).
208  */
ogg_replace_stream(AVFormatContext * s,uint32_t serial,char * magic,int page_size,int probing)209 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size,
210                               int probing)
211 {
212     struct ogg *ogg = s->priv_data;
213     struct ogg_stream *os;
214     const struct ogg_codec *codec;
215     int i = 0;
216 
217     if (ogg->nstreams != 1) {
218         avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
219         return AVERROR_PATCHWELCOME;
220     }
221 
222     /* Check for codecs */
223     codec = ogg_find_codec(magic, page_size);
224     if (!codec && !probing) {
225         av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
226         return AVERROR_INVALIDDATA;
227     }
228 
229     os = &ogg->streams[0];
230     if (os->codec != codec)
231         return AVERROR(EINVAL);
232 
233     os->serial  = serial;
234     os->codec   = codec;
235     os->serial  = serial;
236     os->lastpts = 0;
237     os->lastdts = 0;
238     os->start_trimming = 0;
239     os->end_trimming = 0;
240 
241     /* Chained files have extradata as a new packet */
242     if (codec == &ff_opus_codec)
243         os->header = -1;
244 
245     return i;
246 }
247 
ogg_new_stream(AVFormatContext * s,uint32_t serial)248 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
249 {
250     struct ogg *ogg = s->priv_data;
251     int idx         = ogg->nstreams;
252     AVStream *st;
253     struct ogg_stream *os;
254     size_t size;
255 
256     if (ogg->state) {
257         av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
258                "in between Ogg context save/restore operations.\n");
259         return AVERROR_BUG;
260     }
261 
262     /* Allocate and init a new Ogg Stream */
263     if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
264         !(os = av_realloc(ogg->streams, size)))
265         return AVERROR(ENOMEM);
266     ogg->streams = os;
267     os           = ogg->streams + idx;
268     memset(os, 0, sizeof(*os));
269     os->serial        = serial;
270     os->bufsize       = DECODER_BUFFER_SIZE;
271     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
272     os->header        = -1;
273     os->start_granule = OGG_NOGRANULE_VALUE;
274     if (!os->buf)
275         return AVERROR(ENOMEM);
276 
277     /* Create the associated AVStream */
278     st = avformat_new_stream(s, NULL);
279     if (!st) {
280         av_freep(&os->buf);
281         return AVERROR(ENOMEM);
282     }
283     st->id = idx;
284     avpriv_set_pts_info(st, 64, 1, 1000000);
285 
286     ogg->nstreams++;
287     return idx;
288 }
289 
data_packets_seen(const struct ogg * ogg)290 static int data_packets_seen(const struct ogg *ogg)
291 {
292     int i;
293 
294     for (i = 0; i < ogg->nstreams; i++)
295         if (ogg->streams[i].got_data)
296             return 1;
297     return 0;
298 }
299 
buf_realloc(struct ogg_stream * os,int size)300 static int buf_realloc(struct ogg_stream *os, int size)
301 {
302     /* Even if invalid guarantee there's enough memory to read the page */
303     if (os->bufsize - os->bufpos < size) {
304         uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
305         if (!nb)
306             return AVERROR(ENOMEM);
307         os->buf = nb;
308         os->bufsize *= 2;
309     }
310 
311     return 0;
312 }
313 
ogg_read_page(AVFormatContext * s,int * sid,int probing)314 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
315 {
316     AVIOContext *bc = s->pb;
317     struct ogg *ogg = s->priv_data;
318     struct ogg_stream *os;
319     int ret, i = 0;
320     int flags, nsegs;
321     uint64_t gp;
322     uint32_t serial;
323     uint32_t crc, crc_tmp;
324     int size = 0, idx;
325     int64_t version, page_pos;
326     int64_t start_pos;
327     uint8_t sync[4];
328     uint8_t segments[255];
329     uint8_t *readout_buf;
330     int sp = 0;
331 
332     ret = avio_read(bc, sync, 4);
333     if (ret < 4)
334         return ret < 0 ? ret : AVERROR_EOF;
335 
336     do {
337         int c;
338 
339         if (sync[sp & 3] == 'O' &&
340             sync[(sp + 1) & 3] == 'g' &&
341             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
342             break;
343 
344         if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
345             memset(sync, 0, 4);
346             avio_seek(bc, ogg->page_pos+4, SEEK_SET);
347             ogg->page_pos = -1;
348         }
349 
350         c = avio_r8(bc);
351 
352         if (avio_feof(bc))
353             return AVERROR_EOF;
354 
355         sync[sp++ & 3] = c;
356     } while (i++ < MAX_PAGE_SIZE);
357 
358     if (i >= MAX_PAGE_SIZE) {
359         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
360         return AVERROR_INVALIDDATA;
361     }
362 
363     /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
364     ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
365 
366     /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
367     ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
368     start_pos = avio_tell(bc);
369 
370     version = avio_r8(bc);
371     flags   = avio_r8(bc);
372     gp      = avio_rl64(bc);
373     serial  = avio_rl32(bc);
374     avio_skip(bc, 4); /* seq */
375 
376     crc_tmp = ffio_get_checksum(bc);
377     crc     = avio_rb32(bc);
378     crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
379     ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
380 
381     nsegs    = avio_r8(bc);
382     page_pos = avio_tell(bc) - 27;
383 
384     ret = avio_read(bc, segments, nsegs);
385     if (ret < nsegs)
386         return ret < 0 ? ret : AVERROR_EOF;
387 
388     for (i = 0; i < nsegs; i++)
389         size += segments[i];
390 
391     idx = ogg_find_stream(ogg, serial);
392     if (idx >= 0) {
393         os = ogg->streams + idx;
394 
395         ret = buf_realloc(os, size);
396         if (ret < 0)
397             return ret;
398 
399         readout_buf = os->buf + os->bufpos;
400     } else {
401         readout_buf = av_malloc(size);
402     }
403 
404     ret = avio_read(bc, readout_buf, size);
405     if (ret < size) {
406         if (idx < 0)
407             av_free(readout_buf);
408         return ret < 0 ? ret : AVERROR_EOF;
409     }
410 
411     if (crc ^ ffio_get_checksum(bc)) {
412         av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
413         if (idx < 0)
414             av_free(readout_buf);
415         avio_seek(bc, start_pos, SEEK_SET);
416         *sid = -1;
417         return 0;
418     }
419 
420     /* Since we're almost sure its a valid packet, checking the version after
421      * the checksum lets the demuxer be more tolerant */
422     if (version) {
423         av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
424         if (idx < 0)
425             av_free(readout_buf);
426         avio_seek(bc, start_pos, SEEK_SET);
427         *sid = -1;
428         return 0;
429     }
430 
431     /* CRC is correct so we can be 99% sure there's an actual change here */
432     if (idx < 0) {
433         if (data_packets_seen(ogg))
434             idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
435         else
436             idx = ogg_new_stream(s, serial);
437 
438         if (idx < 0) {
439             av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
440             av_free(readout_buf);
441             return idx;
442         }
443 
444         os = ogg->streams + idx;
445 
446         ret = buf_realloc(os, size);
447         if (ret < 0) {
448             av_free(readout_buf);
449             return ret;
450         }
451 
452         memcpy(os->buf + os->bufpos, readout_buf, size);
453         av_free(readout_buf);
454     }
455 
456     ogg->page_pos = page_pos;
457     os->page_pos  = page_pos;
458     os->nsegs     = nsegs;
459     os->segp      = 0;
460     os->got_data  = !(flags & OGG_FLAG_BOS);
461     os->bufpos   += size;
462     os->granule   = gp;
463     os->flags     = flags;
464     memcpy(os->segments, segments, nsegs);
465     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
466 
467     if (flags & OGG_FLAG_CONT || os->incomplete) {
468         if (!os->psize) {
469             // If this is the very first segment we started
470             // playback in the middle of a continuation packet.
471             // Discard it since we missed the start of it.
472             while (os->segp < os->nsegs) {
473                 int seg = os->segments[os->segp++];
474                 os->pstart += seg;
475                 if (seg < 255)
476                     break;
477             }
478             os->sync_pos = os->page_pos;
479         }
480     } else {
481         os->psize    = 0;
482         os->sync_pos = os->page_pos;
483     }
484 
485     /* This function is always called with sid != NULL */
486     *sid = idx;
487 
488     return 0;
489 }
490 
491 /**
492  * @brief find the next Ogg packet
493  * @param *sid is set to the stream for the packet or -1 if there is
494  *             no matching stream, in that case assume all other return
495  *             values to be uninitialized.
496  * @return negative value on error or EOF.
497  */
ogg_packet(AVFormatContext * s,int * sid,int * dstart,int * dsize,int64_t * fpos)498 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
499                       int64_t *fpos)
500 {
501     struct ogg *ogg = s->priv_data;
502     int idx, i, ret;
503     struct ogg_stream *os;
504     int complete = 0;
505     int segp     = 0, psize = 0;
506 
507     av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
508     if (sid)
509         *sid = -1;
510 
511     do {
512         idx = ogg->curidx;
513 
514         while (idx < 0) {
515             ret = ogg_read_page(s, &idx, 0);
516             if (ret < 0)
517                 return ret;
518         }
519 
520         os = ogg->streams + idx;
521 
522         av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
523                 idx, os->pstart, os->psize, os->segp, os->nsegs);
524 
525         if (!os->codec) {
526             if (os->header < 0) {
527                 os->codec = ogg_find_codec(os->buf, os->bufpos);
528                 if (!os->codec) {
529                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
530                     os->header = 0;
531                     return 0;
532                 }
533             } else {
534                 return 0;
535             }
536         }
537 
538         segp  = os->segp;
539         psize = os->psize;
540 
541         while (os->segp < os->nsegs) {
542             int ss = os->segments[os->segp++];
543             os->psize += ss;
544             if (ss < 255) {
545                 complete = 1;
546                 break;
547             }
548         }
549 
550         if (!complete && os->segp == os->nsegs) {
551             ogg->curidx    = -1;
552             // Do not set incomplete for empty packets.
553             // Together with the code in ogg_read_page
554             // that discards all continuation of empty packets
555             // we would get an infinite loop.
556             os->incomplete = !!os->psize;
557         }
558     } while (!complete);
559 
560 
561     if (os->granule == -1)
562         av_log(s, AV_LOG_WARNING,
563                "Page at %"PRId64" is missing granule\n",
564                os->page_pos);
565 
566     ogg->curidx    = idx;
567     os->incomplete = 0;
568 
569     if (os->header) {
570         if ((ret = os->codec->header(s, idx)) < 0) {
571             av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
572             return ret;
573         }
574         os->header = ret;
575         if (!os->header) {
576             os->segp  = segp;
577             os->psize = psize;
578 
579             // We have reached the first non-header packet in this stream.
580             // Unfortunately more header packets may still follow for others,
581             // but if we continue with header parsing we may lose data packets.
582             ogg->headers = 1;
583 
584             // Update the header state for all streams and
585             // compute the data_offset.
586             if (!s->internal->data_offset)
587                 s->internal->data_offset = os->sync_pos;
588 
589             for (i = 0; i < ogg->nstreams; i++) {
590                 struct ogg_stream *cur_os = ogg->streams + i;
591 
592                 // if we have a partial non-header packet, its start is
593                 // obviously at or after the data start
594                 if (cur_os->incomplete)
595                     s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
596             }
597         } else {
598             os->nb_header++;
599             os->pstart += os->psize;
600             os->psize   = 0;
601         }
602     } else {
603         os->pflags    = 0;
604         os->pduration = 0;
605         if (os->codec && os->codec->packet) {
606             if ((ret = os->codec->packet(s, idx)) < 0) {
607                 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
608                 return ret;
609             }
610         }
611         if (sid)
612             *sid = idx;
613         if (dstart)
614             *dstart = os->pstart;
615         if (dsize)
616             *dsize = os->psize;
617         if (fpos)
618             *fpos = os->sync_pos;
619         os->pstart  += os->psize;
620         os->psize    = 0;
621         if(os->pstart == os->bufpos)
622             os->bufpos = os->pstart = 0;
623         os->sync_pos = os->page_pos;
624     }
625 
626     // determine whether there are more complete packets in this page
627     // if not, the page's granule will apply to this packet
628     os->page_end = 1;
629     for (i = os->segp; i < os->nsegs; i++)
630         if (os->segments[i] < 255) {
631             os->page_end = 0;
632             break;
633         }
634 
635     if (os->segp == os->nsegs)
636         ogg->curidx = -1;
637 
638     return 0;
639 }
640 
ogg_get_length(AVFormatContext * s)641 static int ogg_get_length(AVFormatContext *s)
642 {
643     struct ogg *ogg = s->priv_data;
644     int i, ret;
645     int64_t size, end;
646     int streams_left=0;
647 
648     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
649         return 0;
650 
651 // already set
652     if (s->duration != AV_NOPTS_VALUE)
653         return 0;
654 
655     size = avio_size(s->pb);
656     if (size < 0)
657         return 0;
658     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
659 
660     ret = ogg_save(s);
661     if (ret < 0)
662         return ret;
663     avio_seek(s->pb, end, SEEK_SET);
664     ogg->page_pos = -1;
665 
666     while (!ogg_read_page(s, &i, 1)) {
667         if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
668             ogg->streams[i].codec) {
669             s->streams[i]->duration =
670                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
671             if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
672                 s->streams[i]->duration -= s->streams[i]->start_time;
673                 streams_left-= (ogg->streams[i].got_start==-1);
674                 ogg->streams[i].got_start= 1;
675             } else if(!ogg->streams[i].got_start) {
676                 ogg->streams[i].got_start= -1;
677                 streams_left++;
678             }
679         }
680     }
681 
682     ogg_restore(s);
683 
684     ret = ogg_save(s);
685     if (ret < 0)
686         return ret;
687 
688     avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
689     ogg_reset(s);
690     while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
691         int64_t pts;
692         if (i < 0) continue;
693         pts = ogg_calc_pts(s, i, NULL);
694         if (s->streams[i]->duration == AV_NOPTS_VALUE)
695             continue;
696         if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
697             s->streams[i]->duration -= pts;
698             ogg->streams[i].got_start= 1;
699             streams_left--;
700         }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
701             ogg->streams[i].got_start= 1;
702             streams_left--;
703         }
704     }
705     ogg_restore (s);
706 
707     return 0;
708 }
709 
ogg_read_close(AVFormatContext * s)710 static int ogg_read_close(AVFormatContext *s)
711 {
712     struct ogg *ogg = s->priv_data;
713     int i;
714 
715     for (i = 0; i < ogg->nstreams; i++) {
716         free_stream(s, i);
717     }
718 
719     ogg->nstreams = 0;
720 
721     av_freep(&ogg->streams);
722     return 0;
723 }
724 
ogg_read_header(AVFormatContext * s)725 static int ogg_read_header(AVFormatContext *s)
726 {
727     struct ogg *ogg = s->priv_data;
728     int ret, i;
729 
730     ogg->curidx = -1;
731 
732     //linear headers seek from start
733     do {
734         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
735         if (ret < 0) {
736             ogg_read_close(s);
737             return ret;
738         }
739     } while (!ogg->headers);
740     av_log(s, AV_LOG_TRACE, "found headers\n");
741 
742     for (i = 0; i < ogg->nstreams; i++) {
743         struct ogg_stream *os = ogg->streams + i;
744 
745         if (ogg->streams[i].header < 0) {
746             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
747             ogg->streams[i].codec = NULL;
748             av_freep(&ogg->streams[i].private);
749         } else if (os->codec && os->nb_header < os->codec->nb_header) {
750             av_log(s, AV_LOG_WARNING,
751                    "Headers mismatch for stream %d: "
752                    "expected %d received %d.\n",
753                    i, os->codec->nb_header, os->nb_header);
754             if (s->error_recognition & AV_EF_EXPLODE) {
755                 ogg_read_close(s);
756                 return AVERROR_INVALIDDATA;
757             }
758         }
759         if (os->start_granule != OGG_NOGRANULE_VALUE)
760             os->lastpts = s->streams[i]->start_time =
761                 ogg_gptopts(s, i, os->start_granule, NULL);
762     }
763 
764     //linear granulepos seek from end
765     ret = ogg_get_length(s);
766     if (ret < 0) {
767         ogg_read_close(s);
768         return ret;
769     }
770 
771     return 0;
772 }
773 
ogg_calc_pts(AVFormatContext * s,int idx,int64_t * dts)774 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
775 {
776     struct ogg *ogg       = s->priv_data;
777     struct ogg_stream *os = ogg->streams + idx;
778     int64_t pts           = AV_NOPTS_VALUE;
779 
780     if (dts)
781         *dts = AV_NOPTS_VALUE;
782 
783     if (os->lastpts != AV_NOPTS_VALUE) {
784         pts         = os->lastpts;
785         os->lastpts = AV_NOPTS_VALUE;
786     }
787     if (os->lastdts != AV_NOPTS_VALUE) {
788         if (dts)
789             *dts = os->lastdts;
790         os->lastdts = AV_NOPTS_VALUE;
791     }
792     if (os->page_end) {
793         if (os->granule != -1LL) {
794             if (os->codec && os->codec->granule_is_start)
795                 pts = ogg_gptopts(s, idx, os->granule, dts);
796             else
797                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
798             os->granule = -1LL;
799         }
800     }
801     return pts;
802 }
803 
ogg_validate_keyframe(AVFormatContext * s,int idx,int pstart,int psize)804 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
805 {
806     struct ogg *ogg = s->priv_data;
807     struct ogg_stream *os = ogg->streams + idx;
808     int invalid = 0;
809     if (psize) {
810         switch (s->streams[idx]->codecpar->codec_id) {
811         case AV_CODEC_ID_THEORA:
812             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
813         break;
814         case AV_CODEC_ID_VP8:
815             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
816         }
817         if (invalid) {
818             os->pflags ^= AV_PKT_FLAG_KEY;
819             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
820                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
821         }
822     }
823 }
824 
ogg_read_packet(AVFormatContext * s,AVPacket * pkt)825 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
826 {
827     struct ogg *ogg;
828     struct ogg_stream *os;
829     int idx, ret;
830     int pstart, psize;
831     int64_t fpos, pts, dts;
832 
833     if (s->io_repositioned) {
834         ogg_reset(s);
835         s->io_repositioned = 0;
836     }
837 
838     //Get an ogg packet
839 retry:
840     do {
841         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
842         if (ret < 0)
843             return ret;
844     } while (idx < 0 || !s->streams[idx]);
845 
846     ogg = s->priv_data;
847     os  = ogg->streams + idx;
848 
849     // pflags might not be set until after this
850     pts = ogg_calc_pts(s, idx, &dts);
851     ogg_validate_keyframe(s, idx, pstart, psize);
852 
853     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
854         goto retry;
855     os->keyframe_seek = 0;
856 
857     //Alloc a pkt
858     ret = av_new_packet(pkt, psize);
859     if (ret < 0)
860         return ret;
861     pkt->stream_index = idx;
862     memcpy(pkt->data, os->buf + pstart, psize);
863 
864     pkt->pts      = pts;
865     pkt->dts      = dts;
866     pkt->flags    = os->pflags;
867     pkt->duration = os->pduration;
868     pkt->pos      = fpos;
869 
870     if (os->start_trimming || os->end_trimming) {
871         uint8_t *side_data = av_packet_new_side_data(pkt,
872                                                      AV_PKT_DATA_SKIP_SAMPLES,
873                                                      10);
874         if(!side_data)
875             return AVERROR(ENOMEM);
876          AV_WL32(side_data + 0, os->start_trimming);
877         AV_WL32(side_data + 4, os->end_trimming);
878         os->start_trimming = 0;
879         os->end_trimming = 0;
880     }
881 
882     if (os->new_metadata) {
883         ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE,
884                                       os->new_metadata, os->new_metadata_size);
885         if (ret < 0)
886             return ret;
887 
888         os->new_metadata      = NULL;
889         os->new_metadata_size = 0;
890     }
891 
892     return psize;
893 }
894 
ogg_read_timestamp(AVFormatContext * s,int stream_index,int64_t * pos_arg,int64_t pos_limit)895 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
896                                   int64_t *pos_arg, int64_t pos_limit)
897 {
898     struct ogg *ogg = s->priv_data;
899     AVIOContext *bc = s->pb;
900     int64_t pts     = AV_NOPTS_VALUE;
901     int64_t keypos  = -1;
902     int i;
903     int pstart, psize;
904     avio_seek(bc, *pos_arg, SEEK_SET);
905     ogg_reset(s);
906 
907     while (   avio_tell(bc) <= pos_limit
908            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
909         if (i == stream_index) {
910             struct ogg_stream *os = ogg->streams + stream_index;
911             // Do not trust the last timestamps of an ogm video
912             if (    (os->flags & OGG_FLAG_EOS)
913                 && !(os->flags & OGG_FLAG_BOS)
914                 && os->codec == &ff_ogm_video_codec)
915                 continue;
916             pts = ogg_calc_pts(s, i, NULL);
917             ogg_validate_keyframe(s, i, pstart, psize);
918             if (os->pflags & AV_PKT_FLAG_KEY) {
919                 keypos = *pos_arg;
920             } else if (os->keyframe_seek) {
921                 // if we had a previous keyframe but no pts for it,
922                 // return that keyframe with this pts value.
923                 if (keypos >= 0)
924                     *pos_arg = keypos;
925                 else
926                     pts = AV_NOPTS_VALUE;
927             }
928         }
929         if (pts != AV_NOPTS_VALUE)
930             break;
931     }
932     ogg_reset(s);
933     return pts;
934 }
935 
ogg_read_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)936 static int ogg_read_seek(AVFormatContext *s, int stream_index,
937                          int64_t timestamp, int flags)
938 {
939     struct ogg *ogg       = s->priv_data;
940     struct ogg_stream *os = ogg->streams + stream_index;
941     int ret;
942 
943     av_assert0(stream_index < ogg->nstreams);
944     // Ensure everything is reset even when seeking via
945     // the generated index.
946     ogg_reset(s);
947 
948     // Try seeking to a keyframe first. If this fails (very possible),
949     // av_seek_frame will fall back to ignoring keyframes
950     if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
951         && !(flags & AVSEEK_FLAG_ANY))
952         os->keyframe_seek = 1;
953 
954     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
955     ogg_reset(s);
956     os  = ogg->streams + stream_index;
957     if (ret < 0)
958         os->keyframe_seek = 0;
959     return ret;
960 }
961 
ogg_probe(const AVProbeData * p)962 static int ogg_probe(const AVProbeData *p)
963 {
964     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
965         return AVPROBE_SCORE_MAX;
966     return 0;
967 }
968 
969 AVInputFormat ff_ogg_demuxer = {
970     .name           = "ogg",
971     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
972     .priv_data_size = sizeof(struct ogg),
973     .read_probe     = ogg_probe,
974     .read_header    = ogg_read_header,
975     .read_packet    = ogg_read_packet,
976     .read_close     = ogg_read_close,
977     .read_seek      = ogg_read_seek,
978     .read_timestamp = ogg_read_timestamp,
979     .extensions     = "ogg",
980     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
981 };
982