LCOV - code coverage report
Current view: top level - libavformat - oggparsetheora.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 85 103 82.5 %
Date: 2017-12-13 02:34:56 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /**
       2             :  *    Copyright (C) 2005  Matthieu CASTET, Alex Beregszaszi
       3             :  *
       4             :  *    Permission is hereby granted, free of charge, to any person
       5             :  *    obtaining a copy of this software and associated documentation
       6             :  *    files (the "Software"), to deal in the Software without
       7             :  *    restriction, including without limitation the rights to use, copy,
       8             :  *    modify, merge, publish, distribute, sublicense, and/or sell copies
       9             :  *    of the Software, and to permit persons to whom the Software is
      10             :  *    furnished to do so, subject to the following conditions:
      11             :  *
      12             :  *    The above copyright notice and this permission notice shall be
      13             :  *    included in all copies or substantial portions of the Software.
      14             :  *
      15             :  *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      16             :  *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      17             :  *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      18             :  *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      19             :  *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      20             :  *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      21             :  *    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      22             :  *    DEALINGS IN THE SOFTWARE.
      23             :  **/
      24             : 
      25             : #include <stdlib.h>
      26             : #include "libavutil/bswap.h"
      27             : #include "libavcodec/get_bits.h"
      28             : #include "avformat.h"
      29             : #include "internal.h"
      30             : #include "oggdec.h"
      31             : 
      32             : typedef struct TheoraParams {
      33             :     int gpshift;
      34             :     int gpmask;
      35             :     unsigned version;
      36             : } TheoraParams;
      37             : 
      38           8 : static int theora_header(AVFormatContext *s, int idx)
      39             : {
      40           8 :     struct ogg *ogg       = s->priv_data;
      41           8 :     struct ogg_stream *os = ogg->streams + idx;
      42           8 :     AVStream *st          = s->streams[idx];
      43           8 :     TheoraParams *thp     = os->private;
      44           8 :     int cds               = st->codecpar->extradata_size + os->psize + 2;
      45             :     int err;
      46             :     uint8_t *cdp;
      47             : 
      48           8 :     if (!(os->buf[os->pstart] & 0x80))
      49           2 :         return 0;
      50             : 
      51           6 :     if (!thp) {
      52           2 :         thp = av_mallocz(sizeof(*thp));
      53           2 :         if (!thp)
      54           0 :             return AVERROR(ENOMEM);
      55           2 :         os->private = thp;
      56             :     }
      57             : 
      58           6 :     switch (os->buf[os->pstart]) {
      59           2 :     case 0x80: {
      60             :         GetBitContext gb;
      61             :         AVRational timebase;
      62             : 
      63           2 :         init_get_bits(&gb, os->buf + os->pstart, os->psize * 8);
      64             : 
      65             :         /* 0x80"theora" */
      66           2 :         skip_bits_long(&gb, 7 * 8);
      67             : 
      68           2 :         thp->version = get_bits_long(&gb, 24);
      69           2 :         if (thp->version < 0x030100) {
      70           0 :             av_log(s, AV_LOG_ERROR,
      71             :                    "Too old or unsupported Theora (%x)\n", thp->version);
      72           0 :             return AVERROR(ENOSYS);
      73             :         }
      74             : 
      75           2 :         st->codecpar->width  = get_bits(&gb, 16) << 4;
      76           2 :         st->codecpar->height = get_bits(&gb, 16) << 4;
      77             : 
      78           2 :         if (thp->version >= 0x030400)
      79           0 :             skip_bits(&gb, 100);
      80             : 
      81           2 :         if (thp->version >= 0x030200) {
      82           2 :             int width  = get_bits_long(&gb, 24);
      83           2 :             int height = get_bits_long(&gb, 24);
      84           3 :             if (width  <= st->codecpar->width  && width  > st->codecpar->width  - 16 &&
      85           2 :                 height <= st->codecpar->height && height > st->codecpar->height - 16) {
      86           1 :                 st->codecpar->width  = width;
      87           1 :                 st->codecpar->height = height;
      88             :             }
      89             : 
      90           2 :             skip_bits(&gb, 16);
      91             :         }
      92             : 
      93           2 :         timebase.den = get_bits_long(&gb, 32);
      94           2 :         timebase.num = get_bits_long(&gb, 32);
      95           2 :         if (!(timebase.num > 0 && timebase.den > 0)) {
      96           0 :             av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
      97           0 :             timebase.num = 1;
      98           0 :             timebase.den = 25;
      99             :         }
     100           2 :         avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
     101             : 
     102           2 :         st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
     103           2 :         st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
     104             : 
     105           2 :         if (thp->version >= 0x030200)
     106           2 :             skip_bits_long(&gb, 38);
     107           2 :         if (thp->version >= 0x304000)
     108           0 :             skip_bits(&gb, 2);
     109             : 
     110           2 :         thp->gpshift = get_bits(&gb, 5);
     111           2 :         thp->gpmask  = (1U << thp->gpshift) - 1;
     112             : 
     113           2 :         st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
     114           2 :         st->codecpar->codec_id   = AV_CODEC_ID_THEORA;
     115           2 :         st->need_parsing      = AVSTREAM_PARSE_HEADERS;
     116             :     }
     117           2 :     break;
     118           2 :     case 0x81:
     119           2 :         ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 7, os->psize - 7);
     120           4 :     case 0x82:
     121           4 :         if (!thp->version)
     122           0 :             return AVERROR_INVALIDDATA;
     123           4 :         break;
     124           0 :     default:
     125           0 :         av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
     126           0 :         return AVERROR_INVALIDDATA;
     127             :     }
     128             : 
     129           6 :     if ((err = av_reallocp(&st->codecpar->extradata,
     130           6 :                            cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
     131           0 :         st->codecpar->extradata_size = 0;
     132           0 :         return err;
     133             :     }
     134           6 :     memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
     135             : 
     136           6 :     cdp    = st->codecpar->extradata + st->codecpar->extradata_size;
     137           6 :     *cdp++ = os->psize >> 8;
     138           6 :     *cdp++ = os->psize & 0xff;
     139           6 :     memcpy(cdp, os->buf + os->pstart, os->psize);
     140           6 :     st->codecpar->extradata_size = cds;
     141             : 
     142           6 :     return 1;
     143             : }
     144             : 
     145           8 : static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
     146             :                                int64_t *dts)
     147             : {
     148           8 :     struct ogg *ogg       = ctx->priv_data;
     149           8 :     struct ogg_stream *os = ogg->streams + idx;
     150           8 :     TheoraParams *thp     = os->private;
     151             :     uint64_t iframe, pframe;
     152             : 
     153           8 :     if (!thp)
     154           0 :         return AV_NOPTS_VALUE;
     155             : 
     156           8 :     iframe = gp >> thp->gpshift;
     157           8 :     pframe = gp & thp->gpmask;
     158             : 
     159           8 :     if (thp->version < 0x030201)
     160           0 :         iframe++;
     161             : 
     162           8 :     if (!pframe)
     163           4 :         os->pflags |= AV_PKT_FLAG_KEY;
     164             : 
     165           8 :     if (dts)
     166           4 :         *dts = iframe + pframe;
     167             : 
     168           8 :     return iframe + pframe;
     169             : }
     170             : 
     171          20 : static int theora_packet(AVFormatContext *s, int idx)
     172             : {
     173          20 :     struct ogg *ogg = s->priv_data;
     174          20 :     struct ogg_stream *os = ogg->streams + idx;
     175             :     int duration;
     176             : 
     177             :     /* first packet handling
     178             :        here we parse the duration of each packet in the first page and compare
     179             :        the total duration to the page granule to find the encoder delay and
     180             :        set the first timestamp */
     181             : 
     182          20 :     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
     183             :         int seg;
     184             : 
     185           2 :         duration = 1;
     186           2 :         for (seg = os->segp; seg < os->nsegs; seg++) {
     187           0 :             if (os->segments[seg] < 255)
     188           0 :                 duration ++;
     189             :         }
     190             : 
     191           2 :         os->lastpts = os->lastdts   = theora_gptopts(s, idx, os->granule, NULL) - duration;
     192           2 :         if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
     193           1 :             s->streams[idx]->start_time = os->lastpts;
     194           1 :             if (s->streams[idx]->duration > 0)
     195           1 :                 s->streams[idx]->duration -= s->streams[idx]->start_time;
     196             :         }
     197             :     }
     198             : 
     199             :     /* parse packet duration */
     200          20 :     if (os->psize > 0) {
     201          20 :         os->pduration = 1;
     202             :     }
     203             : 
     204          20 :     return 0;
     205             : }
     206             : 
     207             : const struct ogg_codec ff_theora_codec = {
     208             :     .magic     = "\200theora",
     209             :     .magicsize = 7,
     210             :     .header    = theora_header,
     211             :     .packet    = theora_packet,
     212             :     .gptopts   = theora_gptopts,
     213             :     .nb_header = 3,
     214             : };

Generated by: LCOV version 1.13