• 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 "demux.h"
36 #include "oggdec.h"
37 #include "avformat.h"
38 #include "internal.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 <= ffformatcontext(s)->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 
255     if (ogg->state) {
256         av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
257                "in between Ogg context save/restore operations.\n");
258         return AVERROR_BUG;
259     }
260 
261     /* Allocate and init a new Ogg Stream */
262     if (!(os = av_realloc_array(ogg->streams, ogg->nstreams + 1,
263                                 sizeof(*ogg->streams))))
264         return AVERROR(ENOMEM);
265     ogg->streams = os;
266     os           = ogg->streams + idx;
267     memset(os, 0, sizeof(*os));
268     os->serial        = serial;
269     os->bufsize       = DECODER_BUFFER_SIZE;
270     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
271     os->header        = -1;
272     os->start_granule = OGG_NOGRANULE_VALUE;
273     if (!os->buf)
274         return AVERROR(ENOMEM);
275 
276     /* Create the associated AVStream */
277     st = avformat_new_stream(s, NULL);
278     if (!st) {
279         av_freep(&os->buf);
280         return AVERROR(ENOMEM);
281     }
282     st->id = idx;
283     avpriv_set_pts_info(st, 64, 1, 1000000);
284 
285     ogg->nstreams++;
286     return idx;
287 }
288 
data_packets_seen(const struct ogg * ogg)289 static int data_packets_seen(const struct ogg *ogg)
290 {
291     int i;
292 
293     for (i = 0; i < ogg->nstreams; i++)
294         if (ogg->streams[i].got_data)
295             return 1;
296     return 0;
297 }
298 
buf_realloc(struct ogg_stream * os,int size)299 static int buf_realloc(struct ogg_stream *os, int size)
300 {
301     /* Even if invalid guarantee there's enough memory to read the page */
302     if (os->bufsize - os->bufpos < size) {
303         uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
304         if (!nb)
305             return AVERROR(ENOMEM);
306         os->buf = nb;
307         os->bufsize *= 2;
308     }
309 
310     return 0;
311 }
312 
ogg_read_page(AVFormatContext * s,int * sid,int probing)313 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
314 {
315     AVIOContext *bc = s->pb;
316     struct ogg *ogg = s->priv_data;
317     struct ogg_stream *os;
318     int ret, i = 0;
319     int flags, nsegs;
320     uint64_t gp;
321     uint32_t serial;
322     uint32_t crc, crc_tmp;
323     int size = 0, idx;
324     int64_t version, page_pos;
325     int64_t start_pos;
326     uint8_t sync[4];
327     uint8_t segments[255];
328     uint8_t *readout_buf;
329     int sp = 0;
330 
331     ret = avio_read(bc, sync, 4);
332     if (ret < 4)
333         return ret < 0 ? ret : AVERROR_EOF;
334 
335     do {
336         int c;
337 
338         if (sync[sp & 3] == 'O' &&
339             sync[(sp + 1) & 3] == 'g' &&
340             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
341             break;
342 
343         if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
344             memset(sync, 0, 4);
345             avio_seek(bc, ogg->page_pos+4, SEEK_SET);
346             ogg->page_pos = -1;
347         }
348 
349         c = avio_r8(bc);
350 
351         if (avio_feof(bc))
352             return AVERROR_EOF;
353 
354         sync[sp++ & 3] = c;
355     } while (i++ < MAX_PAGE_SIZE);
356 
357     if (i >= MAX_PAGE_SIZE) {
358         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
359         return AVERROR_INVALIDDATA;
360     }
361 
362     /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
363     ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
364 
365     /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
366     ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
367     start_pos = avio_tell(bc);
368 
369     version = avio_r8(bc);
370     flags   = avio_r8(bc);
371     gp      = avio_rl64(bc);
372     serial  = avio_rl32(bc);
373     avio_skip(bc, 4); /* seq */
374 
375     crc_tmp = ffio_get_checksum(bc);
376     crc     = avio_rb32(bc);
377     crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
378     ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
379 
380     nsegs    = avio_r8(bc);
381     page_pos = avio_tell(bc) - 27;
382 
383     ret = avio_read(bc, segments, nsegs);
384     if (ret < nsegs)
385         return ret < 0 ? ret : AVERROR_EOF;
386 
387     for (i = 0; i < nsegs; i++)
388         size += segments[i];
389 
390     idx = ogg_find_stream(ogg, serial);
391     if (idx >= 0) {
392         os = ogg->streams + idx;
393 
394         ret = buf_realloc(os, size);
395         if (ret < 0)
396             return ret;
397 
398         readout_buf = os->buf + os->bufpos;
399     } else {
400         readout_buf = av_malloc(size);
401     }
402 
403     ret = avio_read(bc, readout_buf, size);
404     if (ret < size) {
405         if (idx < 0)
406             av_free(readout_buf);
407         return ret < 0 ? ret : AVERROR_EOF;
408     }
409 
410     if (crc ^ ffio_get_checksum(bc)) {
411         av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
412         if (idx < 0)
413             av_free(readout_buf);
414         avio_seek(bc, start_pos, SEEK_SET);
415         *sid = -1;
416         return 0;
417     }
418 
419     /* Since we're almost sure its a valid packet, checking the version after
420      * the checksum lets the demuxer be more tolerant */
421     if (version) {
422         av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
423         if (idx < 0)
424             av_free(readout_buf);
425         avio_seek(bc, start_pos, SEEK_SET);
426         *sid = -1;
427         return 0;
428     }
429 
430     /* CRC is correct so we can be 99% sure there's an actual change here */
431     if (idx < 0) {
432         if (data_packets_seen(ogg))
433             idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
434         else
435             idx = ogg_new_stream(s, serial);
436 
437         if (idx < 0) {
438             av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
439             av_free(readout_buf);
440             return idx;
441         }
442 
443         os = ogg->streams + idx;
444 
445         ret = buf_realloc(os, size);
446         if (ret < 0) {
447             av_free(readout_buf);
448             return ret;
449         }
450 
451         memcpy(os->buf + os->bufpos, readout_buf, size);
452         av_free(readout_buf);
453     }
454 
455     ogg->page_pos = page_pos;
456     os->page_pos  = page_pos;
457     os->nsegs     = nsegs;
458     os->segp      = 0;
459     os->got_data  = !(flags & OGG_FLAG_BOS);
460     os->bufpos   += size;
461     os->granule   = gp;
462     os->flags     = flags;
463     memcpy(os->segments, segments, nsegs);
464     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
465 
466     if (flags & OGG_FLAG_CONT || os->incomplete) {
467         if (!os->psize) {
468             // If this is the very first segment we started
469             // playback in the middle of a continuation packet.
470             // Discard it since we missed the start of it.
471             while (os->segp < os->nsegs) {
472                 int seg = os->segments[os->segp++];
473                 os->pstart += seg;
474                 if (seg < 255)
475                     break;
476             }
477             os->sync_pos = os->page_pos;
478         }
479     } else {
480         os->psize    = 0;
481         os->sync_pos = os->page_pos;
482     }
483 
484     /* This function is always called with sid != NULL */
485     *sid = idx;
486 
487     return 0;
488 }
489 
490 /**
491  * @brief find the next Ogg packet
492  * @param *sid is set to the stream for the packet or -1 if there is
493  *             no matching stream, in that case assume all other return
494  *             values to be uninitialized.
495  * @return negative value on error or EOF.
496  */
ogg_packet(AVFormatContext * s,int * sid,int * dstart,int * dsize,int64_t * fpos)497 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
498                       int64_t *fpos)
499 {
500     FFFormatContext *const si = ffformatcontext(s);
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 (!si->data_offset)
587                 si->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                     si->data_offset = FFMIN(si->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, ffformatcontext(s)->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             return ret;
737     } while (!ogg->headers);
738     av_log(s, AV_LOG_TRACE, "found headers\n");
739 
740     for (i = 0; i < ogg->nstreams; i++) {
741         struct ogg_stream *os = ogg->streams + i;
742 
743         if (ogg->streams[i].header < 0) {
744             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
745             ogg->streams[i].codec = NULL;
746             av_freep(&ogg->streams[i].private);
747         } else if (os->codec && os->nb_header < os->codec->nb_header) {
748             av_log(s, AV_LOG_WARNING,
749                    "Headers mismatch for stream %d: "
750                    "expected %d received %d.\n",
751                    i, os->codec->nb_header, os->nb_header);
752             if (s->error_recognition & AV_EF_EXPLODE)
753                 return AVERROR_INVALIDDATA;
754         }
755         if (os->start_granule != OGG_NOGRANULE_VALUE)
756             os->lastpts = s->streams[i]->start_time =
757                 ogg_gptopts(s, i, os->start_granule, NULL);
758     }
759 
760     //linear granulepos seek from end
761     ret = ogg_get_length(s);
762     if (ret < 0)
763         return ret;
764 
765     return 0;
766 }
767 
ogg_calc_pts(AVFormatContext * s,int idx,int64_t * dts)768 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
769 {
770     struct ogg *ogg       = s->priv_data;
771     struct ogg_stream *os = ogg->streams + idx;
772     int64_t pts           = AV_NOPTS_VALUE;
773 
774     if (dts)
775         *dts = AV_NOPTS_VALUE;
776 
777     if (os->lastpts != AV_NOPTS_VALUE) {
778         pts         = os->lastpts;
779         os->lastpts = AV_NOPTS_VALUE;
780     }
781     if (os->lastdts != AV_NOPTS_VALUE) {
782         if (dts)
783             *dts = os->lastdts;
784         os->lastdts = AV_NOPTS_VALUE;
785     }
786     if (os->page_end) {
787         if (os->granule != -1LL) {
788             if (os->codec && os->codec->granule_is_start)
789                 pts = ogg_gptopts(s, idx, os->granule, dts);
790             else
791                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
792             os->granule = -1LL;
793         }
794     }
795     return pts;
796 }
797 
ogg_validate_keyframe(AVFormatContext * s,int idx,int pstart,int psize)798 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
799 {
800     struct ogg *ogg = s->priv_data;
801     struct ogg_stream *os = ogg->streams + idx;
802     int invalid = 0;
803     if (psize) {
804         switch (s->streams[idx]->codecpar->codec_id) {
805         case AV_CODEC_ID_THEORA:
806             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
807         break;
808         case AV_CODEC_ID_VP8:
809             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
810         }
811         if (invalid) {
812             os->pflags ^= AV_PKT_FLAG_KEY;
813             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
814                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
815         }
816     }
817 }
818 
ogg_read_packet(AVFormatContext * s,AVPacket * pkt)819 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
820 {
821     struct ogg *ogg;
822     struct ogg_stream *os;
823     int idx, ret;
824     int pstart, psize;
825     int64_t fpos, pts, dts;
826 
827     if (s->io_repositioned) {
828         ogg_reset(s);
829         s->io_repositioned = 0;
830     }
831 
832     //Get an ogg packet
833 retry:
834     do {
835         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
836         if (ret < 0)
837             return ret;
838     } while (idx < 0 || !s->streams[idx]);
839 
840     ogg = s->priv_data;
841     os  = ogg->streams + idx;
842 
843     // pflags might not be set until after this
844     pts = ogg_calc_pts(s, idx, &dts);
845     ogg_validate_keyframe(s, idx, pstart, psize);
846 
847     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
848         goto retry;
849     os->keyframe_seek = 0;
850 
851     //Alloc a pkt
852     ret = av_new_packet(pkt, psize);
853     if (ret < 0)
854         return ret;
855     pkt->stream_index = idx;
856     memcpy(pkt->data, os->buf + pstart, psize);
857 
858     pkt->pts      = pts;
859     pkt->dts      = dts;
860     pkt->flags    = os->pflags;
861     pkt->duration = os->pduration;
862     pkt->pos      = fpos;
863 
864     if (os->start_trimming || os->end_trimming) {
865         uint8_t *side_data = av_packet_new_side_data(pkt,
866                                                      AV_PKT_DATA_SKIP_SAMPLES,
867                                                      10);
868         if(!side_data)
869             return AVERROR(ENOMEM);
870          AV_WL32(side_data + 0, os->start_trimming);
871         AV_WL32(side_data + 4, os->end_trimming);
872         os->start_trimming = 0;
873         os->end_trimming = 0;
874     }
875 
876     if (os->new_metadata) {
877         ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE,
878                                       os->new_metadata, os->new_metadata_size);
879         if (ret < 0)
880             return ret;
881 
882         os->new_metadata      = NULL;
883         os->new_metadata_size = 0;
884     }
885 
886     return psize;
887 }
888 
ogg_read_timestamp(AVFormatContext * s,int stream_index,int64_t * pos_arg,int64_t pos_limit)889 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
890                                   int64_t *pos_arg, int64_t pos_limit)
891 {
892     struct ogg *ogg = s->priv_data;
893     AVIOContext *bc = s->pb;
894     int64_t pts     = AV_NOPTS_VALUE;
895     int64_t keypos  = -1;
896     int i;
897     int pstart, psize;
898     avio_seek(bc, *pos_arg, SEEK_SET);
899     ogg_reset(s);
900 
901     while (   avio_tell(bc) <= pos_limit
902            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
903         if (i == stream_index) {
904             struct ogg_stream *os = ogg->streams + stream_index;
905             // Do not trust the last timestamps of an ogm video
906             if (    (os->flags & OGG_FLAG_EOS)
907                 && !(os->flags & OGG_FLAG_BOS)
908                 && os->codec == &ff_ogm_video_codec)
909                 continue;
910             pts = ogg_calc_pts(s, i, NULL);
911             ogg_validate_keyframe(s, i, pstart, psize);
912             if (os->pflags & AV_PKT_FLAG_KEY) {
913                 keypos = *pos_arg;
914             } else if (os->keyframe_seek) {
915                 // if we had a previous keyframe but no pts for it,
916                 // return that keyframe with this pts value.
917                 if (keypos >= 0)
918                     *pos_arg = keypos;
919                 else
920                     pts = AV_NOPTS_VALUE;
921             }
922         }
923         if (pts != AV_NOPTS_VALUE)
924             break;
925     }
926     ogg_reset(s);
927     return pts;
928 }
929 
ogg_read_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)930 static int ogg_read_seek(AVFormatContext *s, int stream_index,
931                          int64_t timestamp, int flags)
932 {
933     struct ogg *ogg       = s->priv_data;
934     struct ogg_stream *os = ogg->streams + stream_index;
935     int ret;
936 
937     av_assert0(stream_index < ogg->nstreams);
938     // Ensure everything is reset even when seeking via
939     // the generated index.
940     ogg_reset(s);
941 
942     // Try seeking to a keyframe first. If this fails (very possible),
943     // av_seek_frame will fall back to ignoring keyframes
944     if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
945         && !(flags & AVSEEK_FLAG_ANY))
946         os->keyframe_seek = 1;
947 
948     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
949     ogg_reset(s);
950     os  = ogg->streams + stream_index;
951     if (ret < 0)
952         os->keyframe_seek = 0;
953     return ret;
954 }
955 
ogg_probe(const AVProbeData * p)956 static int ogg_probe(const AVProbeData *p)
957 {
958     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
959         return AVPROBE_SCORE_MAX;
960     return 0;
961 }
962 
963 const AVInputFormat ff_ogg_demuxer = {
964     .name           = "ogg",
965     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
966     .priv_data_size = sizeof(struct ogg),
967     .flags_internal = FF_FMT_INIT_CLEANUP,
968     .read_probe     = ogg_probe,
969     .read_header    = ogg_read_header,
970     .read_packet    = ogg_read_packet,
971     .read_close     = ogg_read_close,
972     .read_seek      = ogg_read_seek,
973     .read_timestamp = ogg_read_timestamp,
974     .extensions     = "ogg",
975     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
976 };
977