LCOV - code coverage report
Current view: top level - libavformat - oggdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 430 531 81.0 %
Date: 2017-12-14 08:27:08 Functions: 19 20 95.0 %

          Line data    Source code
       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[] = {
      43             :     &ff_skeleton_codec,
      44             :     &ff_daala_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             : 
      66          41 : static void free_stream(AVFormatContext *s, int i)
      67             : {
      68          41 :     struct ogg *ogg = s->priv_data;
      69          41 :     struct ogg_stream *stream = &ogg->streams[i];
      70             : 
      71          41 :     av_freep(&stream->buf);
      72          82 :     if (stream->codec &&
      73          41 :         stream->codec->cleanup) {
      74          25 :         stream->codec->cleanup(s, i);
      75             :     }
      76             : 
      77          41 :     av_freep(&stream->private);
      78          41 :     av_freep(&stream->new_metadata);
      79          41 : }
      80             : 
      81             : //FIXME We could avoid some structure duplication
      82          64 : static int ogg_save(AVFormatContext *s)
      83             : {
      84          64 :     struct ogg *ogg = s->priv_data;
      85          64 :     struct ogg_state *ost =
      86          64 :         av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
      87             :     int i;
      88          64 :     int ret = 0;
      89             : 
      90          64 :     if (!ost)
      91           0 :         return AVERROR(ENOMEM);
      92             : 
      93          64 :     ost->pos      = avio_tell(s->pb);
      94          64 :     ost->curidx   = ogg->curidx;
      95          64 :     ost->next     = ogg->state;
      96          64 :     ost->nstreams = ogg->nstreams;
      97          64 :     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
      98             : 
      99         130 :     for (i = 0; i < ogg->nstreams; i++) {
     100          66 :         struct ogg_stream *os = ogg->streams + i;
     101          66 :         os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
     102          66 :         if (os->buf)
     103          66 :             memcpy(os->buf, ost->streams[i].buf, os->bufpos);
     104             :         else
     105           0 :             ret = AVERROR(ENOMEM);
     106          66 :         os->new_metadata      = NULL;
     107          66 :         os->new_metadata_size = 0;
     108             :     }
     109             : 
     110          64 :     ogg->state = ost;
     111             : 
     112          64 :     if (ret < 0)
     113           0 :         ogg_restore(s);
     114             : 
     115          64 :     return ret;
     116             : }
     117             : 
     118          64 : static int ogg_restore(AVFormatContext *s)
     119             : {
     120          64 :     struct ogg *ogg = s->priv_data;
     121          64 :     AVIOContext *bc = s->pb;
     122          64 :     struct ogg_state *ost = ogg->state;
     123             :     int i, err;
     124             : 
     125          64 :     if (!ost)
     126           0 :         return 0;
     127             : 
     128          64 :     ogg->state = ost->next;
     129             : 
     130         130 :         for (i = 0; i < ogg->nstreams; i++) {
     131          66 :             av_freep(&ogg->streams[i].buf);
     132          66 :             if (i >= ost->nstreams || !ost->streams[i].private) {
     133           8 :                 free_stream(s, i);
     134             :             }
     135             :         }
     136             : 
     137          64 :         avio_seek(bc, ost->pos, SEEK_SET);
     138          64 :         ogg->page_pos = -1;
     139          64 :         ogg->curidx   = ost->curidx;
     140          64 :         ogg->nstreams = ost->nstreams;
     141          64 :         if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
     142             :                                      sizeof(*ogg->streams))) < 0) {
     143           0 :             ogg->nstreams = 0;
     144           0 :             return err;
     145             :         } else
     146          64 :             memcpy(ogg->streams, ost->streams,
     147          64 :                    ost->nstreams * sizeof(*ogg->streams));
     148             : 
     149          64 :     av_free(ost);
     150             : 
     151          64 :     return 0;
     152             : }
     153             : 
     154         392 : static int ogg_reset(AVFormatContext *s)
     155             : {
     156         392 :     struct ogg *ogg = s->priv_data;
     157             :     int i;
     158         392 :     int64_t start_pos = avio_tell(s->pb);
     159             : 
     160         785 :     for (i = 0; i < ogg->nstreams; i++) {
     161         393 :         struct ogg_stream *os = ogg->streams + i;
     162         393 :         os->bufpos     = 0;
     163         393 :         os->pstart     = 0;
     164         393 :         os->psize      = 0;
     165         393 :         os->granule    = -1;
     166         393 :         os->lastpts    = AV_NOPTS_VALUE;
     167         393 :         os->lastdts    = AV_NOPTS_VALUE;
     168         393 :         os->sync_pos   = -1;
     169         393 :         os->page_pos   = 0;
     170         393 :         os->nsegs      = 0;
     171         393 :         os->segp       = 0;
     172         393 :         os->incomplete = 0;
     173         393 :         os->got_data = 0;
     174         393 :         if (start_pos <= s->internal->data_offset) {
     175         157 :             os->lastpts = 0;
     176             :         }
     177         393 :         os->end_trimming = 0;
     178         393 :         av_freep(&os->new_metadata);
     179         393 :         os->new_metadata_size = 0;
     180             :     }
     181             : 
     182         392 :     ogg->page_pos = -1;
     183         392 :     ogg->curidx = -1;
     184             : 
     185         392 :     return 0;
     186             : }
     187             : 
     188          33 : static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
     189             : {
     190             :     int i;
     191             : 
     192         189 :     for (i = 0; ogg_codecs[i]; i++)
     193         378 :         if (size >= ogg_codecs[i]->magicsize &&
     194         189 :             !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
     195          33 :             return ogg_codecs[i];
     196             : 
     197           0 :     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           0 : static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
     206             : {
     207           0 :     struct ogg *ogg = s->priv_data;
     208             :     struct ogg_stream *os;
     209             :     const struct ogg_codec *codec;
     210           0 :     int i = 0;
     211             : 
     212           0 :     if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
     213             :         uint8_t magic[8];
     214           0 :         int64_t pos = avio_tell(s->pb);
     215           0 :         avio_skip(s->pb, nsegs);
     216           0 :         avio_read(s->pb, magic, sizeof(magic));
     217           0 :         avio_seek(s->pb, pos, SEEK_SET);
     218           0 :         codec = ogg_find_codec(magic, sizeof(magic));
     219           0 :         if (!codec) {
     220           0 :             av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
     221           0 :             return AVERROR_INVALIDDATA;
     222             :         }
     223           0 :         for (i = 0; i < ogg->nstreams; i++) {
     224           0 :             if (ogg->streams[i].codec == codec)
     225           0 :                 break;
     226             :         }
     227           0 :         if (i >= ogg->nstreams)
     228           0 :             return ogg_new_stream(s, serial);
     229           0 :     } else if (ogg->nstreams != 1) {
     230           0 :         avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
     231           0 :         return AVERROR_PATCHWELCOME;
     232             :     }
     233             : 
     234           0 :     os = &ogg->streams[i];
     235             : 
     236           0 :     os->serial  = serial;
     237           0 :     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          33 : static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
     261             : {
     262          33 :     struct ogg *ogg = s->priv_data;
     263          33 :     int idx         = ogg->nstreams;
     264             :     AVStream *st;
     265             :     struct ogg_stream *os;
     266             :     size_t size;
     267             : 
     268          33 :     if (ogg->state) {
     269           0 :         av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
     270             :                "in between Ogg context save/restore operations.\n");
     271           0 :         return AVERROR_BUG;
     272             :     }
     273             : 
     274             :     /* Allocate and init a new Ogg Stream */
     275          66 :     if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
     276          33 :         !(os = av_realloc(ogg->streams, size)))
     277           0 :         return AVERROR(ENOMEM);
     278          33 :     ogg->streams = os;
     279          33 :     os           = ogg->streams + idx;
     280          33 :     memset(os, 0, sizeof(*os));
     281          33 :     os->serial        = serial;
     282          33 :     os->bufsize       = DECODER_BUFFER_SIZE;
     283          33 :     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
     284          33 :     os->header        = -1;
     285          33 :     os->start_granule = OGG_NOGRANULE_VALUE;
     286          33 :     if (!os->buf)
     287           0 :         return AVERROR(ENOMEM);
     288             : 
     289             :     /* Create the associated AVStream */
     290          33 :     st = avformat_new_stream(s, NULL);
     291          33 :     if (!st) {
     292           0 :         av_freep(&os->buf);
     293           0 :         return AVERROR(ENOMEM);
     294             :     }
     295          33 :     st->id = idx;
     296          33 :     avpriv_set_pts_info(st, 64, 1, 1000000);
     297             : 
     298          33 :     ogg->nstreams++;
     299          33 :     return idx;
     300             : }
     301             : 
     302         363 : static int ogg_new_buf(struct ogg *ogg, int idx)
     303             : {
     304         363 :     struct ogg_stream *os = ogg->streams + idx;
     305         363 :     uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
     306         363 :     int size = os->bufpos - os->pstart;
     307             : 
     308         363 :     if (!nb)
     309           0 :         return AVERROR(ENOMEM);
     310             : 
     311         363 :     if (os->buf) {
     312         363 :         memcpy(nb, os->buf + os->pstart, size);
     313         363 :         av_free(os->buf);
     314             :     }
     315             : 
     316         363 :     os->buf    = nb;
     317         363 :     os->bufpos = size;
     318         363 :     os->pstart = 0;
     319             : 
     320         363 :     return 0;
     321             : }
     322             : 
     323          33 : static int data_packets_seen(const struct ogg *ogg)
     324             : {
     325             :     int i;
     326             : 
     327          34 :     for (i = 0; i < ogg->nstreams; i++)
     328           1 :         if (ogg->streams[i].got_data)
     329           0 :             return 1;
     330          33 :     return 0;
     331             : }
     332             : 
     333        1339 : static int ogg_read_page(AVFormatContext *s, int *sid)
     334             : {
     335        1339 :     AVIOContext *bc = s->pb;
     336        1339 :     struct ogg *ogg = s->priv_data;
     337             :     struct ogg_stream *os;
     338        1339 :     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        1339 :     int sp = 0;
     345             : 
     346        1339 :     ret = avio_read(bc, sync, 4);
     347        1339 :     if (ret < 4)
     348          20 :         return ret < 0 ? ret : AVERROR_EOF;
     349             : 
     350             :     do {
     351             :         int c;
     352             : 
     353      641807 :         if (sync[sp & 3] == 'O' &&
     354        4482 :             sync[(sp + 1) & 3] == 'g' &&
     355        2498 :             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
     356        1245 :             break;
     357             : 
     358      637333 :         if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
     359           0 :             memset(sync, 0, 4);
     360           0 :             avio_seek(bc, ogg->page_pos+4, SEEK_SET);
     361           0 :             ogg->page_pos = -1;
     362             :         }
     363             : 
     364      637333 :         c = avio_r8(bc);
     365             : 
     366      637333 :         if (avio_feof(bc))
     367          74 :             return AVERROR_EOF;
     368             : 
     369      637259 :         sync[sp++ & 3] = c;
     370      637259 :     } while (i++ < MAX_PAGE_SIZE);
     371             : 
     372        1245 :     if (i >= MAX_PAGE_SIZE) {
     373           0 :         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
     374           0 :         return AVERROR_INVALIDDATA;
     375             :     }
     376             : 
     377        1245 :     if (avio_r8(bc) != 0) {      /* version */
     378           0 :         av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
     379           0 :         return AVERROR_INVALIDDATA;
     380             :     }
     381             : 
     382        1245 :     flags  = avio_r8(bc);
     383        1245 :     gp     = avio_rl64(bc);
     384        1245 :     serial = avio_rl32(bc);
     385        1245 :     avio_skip(bc, 8); /* seq, crc */
     386        1245 :     nsegs  = avio_r8(bc);
     387             : 
     388        1245 :     idx = ogg_find_stream(ogg, serial);
     389        1245 :     if (idx < 0) {
     390          33 :         if (data_packets_seen(ogg))
     391           0 :             idx = ogg_replace_stream(s, serial, nsegs);
     392             :         else
     393          33 :             idx = ogg_new_stream(s, serial);
     394             : 
     395          33 :         if (idx < 0) {
     396           0 :             av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
     397           0 :             return idx;
     398             :         }
     399             :     }
     400             : 
     401        1245 :     os = ogg->streams + idx;
     402        1245 :     ogg->page_pos =
     403        1245 :     os->page_pos = avio_tell(bc) - 27;
     404             : 
     405        1245 :     if (os->psize > 0) {
     406         363 :         ret = ogg_new_buf(ogg, idx);
     407         363 :         if (ret < 0)
     408           0 :             return ret;
     409             :     }
     410             : 
     411        1245 :     ret = avio_read(bc, os->segments, nsegs);
     412        1245 :     if (ret < nsegs)
     413           0 :         return ret < 0 ? ret : AVERROR_EOF;
     414             : 
     415        1245 :     os->nsegs = nsegs;
     416        1245 :     os->segp  = 0;
     417             : 
     418        1245 :     size = 0;
     419       39273 :     for (i = 0; i < nsegs; i++)
     420       38028 :         size += os->segments[i];
     421             : 
     422        1245 :     if (!(flags & OGG_FLAG_BOS))
     423        1191 :         os->got_data = 1;
     424             : 
     425        1245 :     if (flags & OGG_FLAG_CONT || os->incomplete) {
     426        1066 :         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         463 :             while (os->segp < os->nsegs) {
     431         292 :                 int seg = os->segments[os->segp++];
     432         292 :                 os->pstart += seg;
     433         292 :                 if (seg < 255)
     434         171 :                     break;
     435             :             }
     436         171 :             os->sync_pos = os->page_pos;
     437             :         }
     438             :     } else {
     439         712 :         os->psize    = 0;
     440         712 :         os->sync_pos = os->page_pos;
     441             :     }
     442             : 
     443        1245 :     if (os->bufsize - os->bufpos < size) {
     444          32 :         uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
     445          32 :         if (!nb)
     446           0 :             return AVERROR(ENOMEM);
     447          32 :         memcpy(nb, os->buf, os->bufpos);
     448          32 :         av_free(os->buf);
     449          32 :         os->buf = nb;
     450             :     }
     451             : 
     452        1245 :     ret = avio_read(bc, os->buf + os->bufpos, size);
     453        1245 :     if (ret < size)
     454          44 :         return ret < 0 ? ret : AVERROR_EOF;
     455             : 
     456        1201 :     os->bufpos += size;
     457        1201 :     os->granule = gp;
     458        1201 :     os->flags   = flags;
     459             : 
     460        1201 :     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     461        1201 :     if (sid)
     462        1201 :         *sid = idx;
     463             : 
     464        1201 :     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       10317 : static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
     475             :                       int64_t *fpos)
     476             : {
     477       10317 :     struct ogg *ogg = s->priv_data;
     478             :     int idx, i, ret;
     479             :     struct ogg_stream *os;
     480       10317 :     int complete = 0;
     481       10317 :     int segp     = 0, psize = 0;
     482             : 
     483       10317 :     av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
     484       10317 :     if (sid)
     485       10193 :         *sid = -1;
     486             : 
     487             :     do {
     488       10664 :         idx = ogg->curidx;
     489             : 
     490       22145 :         while (idx < 0) {
     491         923 :             ret = ogg_read_page(s, &idx);
     492         923 :             if (ret < 0)
     493         106 :                 return ret;
     494             :         }
     495             : 
     496       10558 :         os = ogg->streams + idx;
     497             : 
     498       10558 :         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       10558 :         if (!os->codec) {
     502          33 :             if (os->header < 0) {
     503          33 :                 os->codec = ogg_find_codec(os->buf, os->bufpos);
     504          33 :                 if (!os->codec) {
     505           0 :                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
     506           0 :                     os->header = 0;
     507           0 :                     return 0;
     508             :                 }
     509             :             } else {
     510           0 :                 return 0;
     511             :             }
     512             :         }
     513             : 
     514       10558 :         segp  = os->segp;
     515       10558 :         psize = os->psize;
     516             : 
     517       32511 :         while (os->segp < os->nsegs) {
     518       21606 :             int ss = os->segments[os->segp++];
     519       21606 :             os->psize += ss;
     520       21606 :             if (ss < 255) {
     521       10211 :                 complete = 1;
     522       10211 :                 break;
     523             :             }
     524             :         }
     525             : 
     526       10558 :         if (!complete && os->segp == os->nsegs) {
     527         347 :             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         347 :             os->incomplete = !!os->psize;
     533             :         }
     534       10558 :     } while (!complete);
     535             : 
     536             : 
     537       10211 :     if (os->granule == -1)
     538         178 :         av_log(s, AV_LOG_WARNING,
     539             :                "Page at %"PRId64" is missing granule\n",
     540             :                os->page_pos);
     541             : 
     542       10211 :     ogg->curidx    = idx;
     543       10211 :     os->incomplete = 0;
     544             : 
     545       10211 :     if (os->header) {
     546         126 :         if ((ret = os->codec->header(s, idx)) < 0) {
     547           0 :             av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
     548           0 :             return ret;
     549             :         }
     550         126 :         os->header = ret;
     551         126 :         if (!os->header) {
     552          34 :             os->segp  = segp;
     553          34 :             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          34 :             ogg->headers = 1;
     559             : 
     560             :             // Update the header state for all streams and
     561             :             // compute the data_offset.
     562          34 :             if (!s->internal->data_offset)
     563          32 :                 s->internal->data_offset = os->sync_pos;
     564             : 
     565          71 :             for (i = 0; i < ogg->nstreams; i++) {
     566          37 :                 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          37 :                 if (cur_os->incomplete)
     571           0 :                     s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
     572             :             }
     573             :         } else {
     574          92 :             os->nb_header++;
     575          92 :             os->pstart += os->psize;
     576          92 :             os->psize   = 0;
     577             :         }
     578             :     } else {
     579       10085 :         os->pflags    = 0;
     580       10085 :         os->pduration = 0;
     581       10085 :         if (os->codec && os->codec->packet) {
     582        9984 :             if ((ret = os->codec->packet(s, idx)) < 0) {
     583           0 :                 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
     584           0 :                 return ret;
     585             :             }
     586             :         }
     587       10085 :         if (sid)
     588       10085 :             *sid = idx;
     589       10085 :         if (dstart)
     590       10052 :             *dstart = os->pstart;
     591       10085 :         if (dsize)
     592       10052 :             *dsize = os->psize;
     593       10085 :         if (fpos)
     594       10052 :             *fpos = os->sync_pos;
     595       10085 :         os->pstart  += os->psize;
     596       10085 :         os->psize    = 0;
     597       10085 :         if(os->pstart == os->bufpos)
     598         303 :             os->bufpos = os->pstart = 0;
     599       10085 :         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       10211 :     os->page_end = 1;
     605       16221 :     for (i = os->segp; i < os->nsegs; i++)
     606       15616 :         if (os->segments[i] < 255) {
     607        9606 :             os->page_end = 0;
     608        9606 :             break;
     609             :         }
     610             : 
     611       10211 :     if (os->segp == os->nsegs)
     612         369 :         ogg->curidx = -1;
     613             : 
     614       10211 :     return 0;
     615             : }
     616             : 
     617          32 : static int ogg_get_length(AVFormatContext *s)
     618             : {
     619          32 :     struct ogg *ogg = s->priv_data;
     620             :     int i, ret;
     621             :     int64_t size, end;
     622          32 :     int streams_left=0;
     623             : 
     624          32 :     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
     625           0 :         return 0;
     626             : 
     627             : // already set
     628          32 :     if (s->duration != AV_NOPTS_VALUE)
     629           0 :         return 0;
     630             : 
     631          32 :     size = avio_size(s->pb);
     632          32 :     if (size < 0)
     633           0 :         return 0;
     634          32 :     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
     635             : 
     636          32 :     ret = ogg_save(s);
     637          32 :     if (ret < 0)
     638           0 :         return ret;
     639          32 :     avio_seek(s->pb, end, SEEK_SET);
     640          32 :     ogg->page_pos = -1;
     641             : 
     642         448 :     while (!ogg_read_page(s, &i)) {
     643         740 :         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
     644         356 :             ogg->streams[i].codec) {
     645         712 :             s->streams[i]->duration =
     646         712 :                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
     647         356 :             if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
     648           0 :                 s->streams[i]->duration -= s->streams[i]->start_time;
     649           0 :                 streams_left-= (ogg->streams[i].got_start==-1);
     650           0 :                 ogg->streams[i].got_start= 1;
     651         356 :             } else if(!ogg->streams[i].got_start) {
     652          33 :                 ogg->streams[i].got_start= -1;
     653          33 :                 streams_left++;
     654             :             }
     655             :         }
     656             :     }
     657             : 
     658          32 :     ogg_restore(s);
     659             : 
     660          32 :     ret = ogg_save(s);
     661          32 :     if (ret < 0)
     662           0 :         return ret;
     663             : 
     664          32 :     avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
     665          32 :     ogg_reset(s);
     666          98 :     while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
     667             :         int64_t pts;
     668          34 :         if (i < 0) continue;
     669          33 :         pts = ogg_calc_pts(s, i, NULL);
     670          33 :         if (s->streams[i]->duration == AV_NOPTS_VALUE)
     671           0 :             continue;
     672          33 :         if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
     673           3 :             s->streams[i]->duration -= pts;
     674           3 :             ogg->streams[i].got_start= 1;
     675           3 :             streams_left--;
     676          30 :         }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
     677          30 :             ogg->streams[i].got_start= 1;
     678          30 :             streams_left--;
     679             :         }
     680             :     }
     681          32 :     ogg_restore (s);
     682             : 
     683          32 :     return 0;
     684             : }
     685             : 
     686          32 : static int ogg_read_close(AVFormatContext *s)
     687             : {
     688          32 :     struct ogg *ogg = s->priv_data;
     689             :     int i;
     690             : 
     691          65 :     for (i = 0; i < ogg->nstreams; i++) {
     692          33 :         free_stream(s, i);
     693             :     }
     694             : 
     695          32 :     ogg->nstreams = 0;
     696             : 
     697          32 :     av_freep(&ogg->streams);
     698          32 :     return 0;
     699             : }
     700             : 
     701          32 : static int ogg_read_header(AVFormatContext *s)
     702             : {
     703          32 :     struct ogg *ogg = s->priv_data;
     704             :     int ret, i;
     705             : 
     706          32 :     ogg->curidx = -1;
     707             : 
     708             :     //linear headers seek from start
     709             :     do {
     710         124 :         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
     711         124 :         if (ret < 0) {
     712           0 :             ogg_read_close(s);
     713           0 :             return ret;
     714             :         }
     715         124 :     } while (!ogg->headers);
     716          32 :     av_log(s, AV_LOG_TRACE, "found headers\n");
     717             : 
     718          65 :     for (i = 0; i < ogg->nstreams; i++) {
     719          33 :         struct ogg_stream *os = ogg->streams + i;
     720             : 
     721          33 :         if (ogg->streams[i].header < 0) {
     722           0 :             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
     723           0 :             ogg->streams[i].codec = NULL;
     724           0 :             av_freep(&ogg->streams[i].private);
     725          33 :         } else if (os->codec && os->nb_header < os->codec->nb_header) {
     726           0 :             av_log(s, AV_LOG_WARNING,
     727             :                    "Headers mismatch for stream %d: "
     728             :                    "expected %d received %d.\n",
     729           0 :                    i, os->codec->nb_header, os->nb_header);
     730           0 :             if (s->error_recognition & AV_EF_EXPLODE) {
     731           0 :                 ogg_read_close(s);
     732           0 :                 return AVERROR_INVALIDDATA;
     733             :             }
     734             :         }
     735          33 :         if (os->start_granule != OGG_NOGRANULE_VALUE)
     736           0 :             os->lastpts = s->streams[i]->start_time =
     737           0 :                 ogg_gptopts(s, i, os->start_granule, NULL);
     738             :     }
     739             : 
     740             :     //linear granulepos seek from end
     741          32 :     ret = ogg_get_length(s);
     742          32 :     if (ret < 0) {
     743           0 :         ogg_read_close(s);
     744           0 :         return ret;
     745             :     }
     746             : 
     747          32 :     return 0;
     748             : }
     749             : 
     750       10085 : static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
     751             : {
     752       10085 :     struct ogg *ogg       = s->priv_data;
     753       10085 :     struct ogg_stream *os = ogg->streams + idx;
     754       10085 :     int64_t pts           = AV_NOPTS_VALUE;
     755             : 
     756       10085 :     if (dts)
     757        9978 :         *dts = AV_NOPTS_VALUE;
     758             : 
     759       10085 :     if (os->lastpts != AV_NOPTS_VALUE) {
     760        9738 :         pts         = os->lastpts;
     761        9738 :         os->lastpts = AV_NOPTS_VALUE;
     762             :     }
     763       10085 :     if (os->lastdts != AV_NOPTS_VALUE) {
     764        9647 :         if (dts)
     765        9605 :             *dts = os->lastdts;
     766        9647 :         os->lastdts = AV_NOPTS_VALUE;
     767             :     }
     768       10085 :     if (os->page_end) {
     769         526 :         if (os->granule != -1LL) {
     770         517 :             if (os->codec && os->codec->granule_is_start)
     771           0 :                 pts = ogg_gptopts(s, idx, os->granule, dts);
     772             :             else
     773         517 :                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
     774         517 :             os->granule = -1LL;
     775             :         }
     776             :     }
     777       10085 :     return pts;
     778             : }
     779             : 
     780       10052 : static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
     781             : {
     782       10052 :     struct ogg *ogg = s->priv_data;
     783       10052 :     struct ogg_stream *os = ogg->streams + idx;
     784       10052 :     int invalid = 0;
     785       10052 :     if (psize) {
     786       10052 :         switch (s->streams[idx]->codecpar->codec_id) {
     787          18 :         case AV_CODEC_ID_THEORA:
     788          18 :             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
     789          18 :         break;
     790         181 :         case AV_CODEC_ID_VP8:
     791         181 :             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
     792             :         }
     793       10052 :         if (invalid) {
     794           2 :             os->pflags ^= AV_PKT_FLAG_KEY;
     795           2 :             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
     796           2 :                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
     797             :         }
     798             :     }
     799       10052 : }
     800             : 
     801       10006 : static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
     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       10006 :     if (s->io_repositioned) {
     810           0 :         ogg_reset(s);
     811           0 :         s->io_repositioned = 0;
     812             :     }
     813             : 
     814             :     //Get an ogg packet
     815       20014 : retry:
     816             :     do {
     817       10007 :         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
     818       10007 :         if (ret < 0)
     819          28 :             return ret;
     820       19957 :     } while (idx < 0 || !s->streams[idx]);
     821             : 
     822        9978 :     ogg = s->priv_data;
     823        9978 :     os  = ogg->streams + idx;
     824             : 
     825             :     // pflags might not be set until after this
     826        9978 :     pts = ogg_calc_pts(s, idx, &dts);
     827        9978 :     ogg_validate_keyframe(s, idx, pstart, psize);
     828             : 
     829        9978 :     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
     830           0 :         goto retry;
     831        9978 :     os->keyframe_seek = 0;
     832             : 
     833             :     //Alloc a pkt
     834        9978 :     ret = av_new_packet(pkt, psize);
     835        9978 :     if (ret < 0)
     836           0 :         return ret;
     837        9978 :     pkt->stream_index = idx;
     838        9978 :     memcpy(pkt->data, os->buf + pstart, psize);
     839             : 
     840        9978 :     pkt->pts      = pts;
     841        9978 :     pkt->dts      = dts;
     842        9978 :     pkt->flags    = os->pflags;
     843        9978 :     pkt->duration = os->pduration;
     844        9978 :     pkt->pos      = fpos;
     845             : 
     846        9978 :     if (os->end_trimming) {
     847           1 :         uint8_t *side_data = av_packet_new_side_data(pkt,
     848             :                                                      AV_PKT_DATA_SKIP_SAMPLES,
     849             :                                                      10);
     850           1 :         if(!side_data)
     851           0 :             goto fail;
     852           1 :         AV_WL32(side_data + 4, os->end_trimming);
     853           1 :         os->end_trimming = 0;
     854             :     }
     855             : 
     856        9978 :     if (os->new_metadata) {
     857          25 :         uint8_t *side_data = av_packet_new_side_data(pkt,
     858             :                                                      AV_PKT_DATA_METADATA_UPDATE,
     859          25 :                                                      os->new_metadata_size);
     860          25 :         if(!side_data)
     861           0 :             goto fail;
     862             : 
     863          25 :         memcpy(side_data, os->new_metadata, os->new_metadata_size);
     864          25 :         av_freep(&os->new_metadata);
     865          25 :         os->new_metadata_size = 0;
     866             :     }
     867             : 
     868        9978 :     return psize;
     869           0 : fail:
     870           0 :     av_packet_unref(pkt);
     871           0 :     return AVERROR(ENOMEM);
     872             : }
     873             : 
     874         152 : static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
     875             :                                   int64_t *pos_arg, int64_t pos_limit)
     876             : {
     877         152 :     struct ogg *ogg = s->priv_data;
     878         152 :     AVIOContext *bc = s->pb;
     879         152 :     int64_t pts     = AV_NOPTS_VALUE;
     880         152 :     int64_t keypos  = -1;
     881             :     int i;
     882             :     int pstart, psize;
     883         152 :     avio_seek(bc, *pos_arg, SEEK_SET);
     884         152 :     ogg_reset(s);
     885             : 
     886         152 :     while (   avio_tell(bc) <= pos_limit
     887         152 :            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
     888          74 :         if (i == stream_index) {
     889          74 :             struct ogg_stream *os = ogg->streams + stream_index;
     890             :             // Do not trust the last timestamps of an ogm video
     891          74 :             if (    (os->flags & OGG_FLAG_EOS)
     892          26 :                 && !(os->flags & OGG_FLAG_BOS)
     893          26 :                 && os->codec == &ff_ogm_video_codec)
     894           0 :                 continue;
     895          74 :             pts = ogg_calc_pts(s, i, NULL);
     896          74 :             ogg_validate_keyframe(s, i, pstart, psize);
     897          74 :             if (os->pflags & AV_PKT_FLAG_KEY) {
     898           0 :                 keypos = *pos_arg;
     899          74 :             } 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           0 :                 if (keypos >= 0)
     903           0 :                     *pos_arg = keypos;
     904             :                 else
     905           0 :                     pts = AV_NOPTS_VALUE;
     906             :             }
     907             :         }
     908          74 :         if (pts != AV_NOPTS_VALUE)
     909          74 :             break;
     910             :     }
     911         152 :     ogg_reset(s);
     912         152 :     return pts;
     913             : }
     914             : 
     915          28 : static int ogg_read_seek(AVFormatContext *s, int stream_index,
     916             :                          int64_t timestamp, int flags)
     917             : {
     918          28 :     struct ogg *ogg       = s->priv_data;
     919          28 :     struct ogg_stream *os = ogg->streams + stream_index;
     920             :     int ret;
     921             : 
     922          28 :     av_assert0(stream_index < ogg->nstreams);
     923             :     // Ensure everything is reset even when seeking via
     924             :     // the generated index.
     925          28 :     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          28 :     if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
     930           0 :         && !(flags & AVSEEK_FLAG_ANY))
     931           0 :         os->keyframe_seek = 1;
     932             : 
     933          28 :     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
     934          28 :     ogg_reset(s);
     935          28 :     os  = ogg->streams + stream_index;
     936          28 :     if (ret < 0)
     937           0 :         os->keyframe_seek = 0;
     938          28 :     return ret;
     939             : }
     940             : 
     941        6130 : static int ogg_probe(AVProbeData *p)
     942             : {
     943        6130 :     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
     944          32 :         return AVPROBE_SCORE_MAX;
     945        6098 :     return 0;
     946             : }
     947             : 
     948             : AVInputFormat ff_ogg_demuxer = {
     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",
     959             :     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
     960             : };

Generated by: LCOV version 1.13