LCOV - code coverage report
Current view: top level - libavformat - oggparsevp8.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 71 87.3 %
Date: 2017-12-14 01:15:32 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * On2 VP8 parser for Ogg
       3             :  * Copyright (C) 2013 James Almer
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include "libavutil/intreadwrite.h"
      23             : 
      24             : #include "avformat.h"
      25             : #include "internal.h"
      26             : #include "oggdec.h"
      27             : 
      28             : #define VP8_HEADER_SIZE 26
      29             : 
      30           5 : static int vp8_header(AVFormatContext *s, int idx)
      31             : {
      32           5 :     struct ogg *ogg = s->priv_data;
      33           5 :     struct ogg_stream *os = ogg->streams + idx;
      34           5 :     uint8_t *p = os->buf + os->pstart;
      35           5 :     AVStream *st = s->streams[idx];
      36             :     AVRational framerate;
      37             : 
      38           5 :     if (os->psize < 7 || p[0] != 0x4f)
      39           2 :         return 0;
      40             : 
      41           3 :     switch (p[5]){
      42           2 :     case 0x01:
      43           2 :         if (os->psize < VP8_HEADER_SIZE) {
      44           0 :             av_log(s, AV_LOG_ERROR, "Invalid OggVP8 header packet");
      45           0 :             return AVERROR_INVALIDDATA;
      46             :         }
      47             : 
      48           2 :         if (p[6] != 1) {
      49           0 :             av_log(s, AV_LOG_WARNING,
      50           0 :                    "Unknown OggVP8 version %d.%d\n", p[6], p[7]);
      51           0 :             return AVERROR_INVALIDDATA;
      52             :         }
      53             : 
      54           2 :         st->codecpar->width         = AV_RB16(p +  8);
      55           2 :         st->codecpar->height        = AV_RB16(p + 10);
      56           2 :         st->sample_aspect_ratio.num = AV_RB24(p + 12);
      57           2 :         st->sample_aspect_ratio.den = AV_RB24(p + 15);
      58           2 :         framerate.num               = AV_RB32(p + 18);
      59           2 :         framerate.den               = AV_RB32(p + 22);
      60             : 
      61           2 :         avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
      62           2 :         st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
      63           2 :         st->codecpar->codec_id   = AV_CODEC_ID_VP8;
      64           2 :         st->need_parsing      = AVSTREAM_PARSE_HEADERS;
      65           2 :         break;
      66           1 :     case 0x02:
      67           1 :         if (p[6] != 0x20)
      68           0 :             return AVERROR_INVALIDDATA;
      69           1 :         ff_vorbis_stream_comment(s, st, p + 7, os->psize - 7);
      70           1 :         break;
      71           0 :     default:
      72           0 :         av_log(s, AV_LOG_ERROR, "Unknown VP8 header type 0x%02X\n", p[5]);
      73           0 :         return AVERROR_INVALIDDATA;
      74             :     }
      75             : 
      76           3 :     return 1;
      77             : }
      78             : 
      79         193 : static uint64_t vp8_gptopts(AVFormatContext *s, int idx,
      80             :                             uint64_t granule, int64_t *dts)
      81             : {
      82         193 :     struct ogg *ogg = s->priv_data;
      83         193 :     struct ogg_stream *os = ogg->streams + idx;
      84             : 
      85         193 :     int invcnt    = !((granule >> 30) & 3);
      86             :     // If page granule is that of an invisible vp8 frame, its pts will be
      87             :     // that of the end of the next visible frame. We subtract 1 for those
      88             :     // to prevent messing up pts calculations.
      89         193 :     uint64_t pts  = (granule >> 32) - invcnt;
      90         193 :     uint32_t dist = (granule >>  3) & 0x07ffffff;
      91             : 
      92         193 :     if (!dist)
      93           4 :         os->pflags |= AV_PKT_FLAG_KEY;
      94             : 
      95         193 :     if (dts)
      96          21 :         *dts = pts;
      97             : 
      98         193 :     return pts;
      99             : }
     100             : 
     101         183 : static int vp8_packet(AVFormatContext *s, int idx)
     102             : {
     103         183 :     struct ogg *ogg = s->priv_data;
     104         183 :     struct ogg_stream *os = ogg->streams + idx;
     105         183 :     uint8_t *p = os->buf + os->pstart;
     106             : 
     107         348 :     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) &&
     108         165 :         !(os->flags & OGG_FLAG_EOS)) {
     109             :         int seg;
     110             :         int duration;
     111         156 :         uint8_t *last_pkt = p;
     112             :         uint8_t *next_pkt;
     113             : 
     114         156 :         seg = os->segp;
     115         156 :         duration = (last_pkt[0] >> 4) & 1;
     116         156 :         next_pkt = last_pkt += os->psize;
     117        2424 :         for (; seg < os->nsegs; seg++) {
     118        2268 :             if (os->segments[seg] < 255) {
     119        1207 :                 duration += (last_pkt[0] >> 4) & 1;
     120        1207 :                 last_pkt  = next_pkt + os->segments[seg];
     121             :             }
     122        2268 :             next_pkt += os->segments[seg];
     123             :         }
     124         156 :         os->lastpts =
     125         156 :         os->lastdts = vp8_gptopts(s, idx, os->granule, NULL) - duration;
     126         156 :         if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
     127           2 :             s->streams[idx]->start_time = os->lastpts;
     128           2 :             if (s->streams[idx]->duration && s->streams[idx]->duration != AV_NOPTS_VALUE)
     129           2 :                 s->streams[idx]->duration -= s->streams[idx]->start_time;
     130             :         }
     131             :     }
     132             : 
     133         183 :     if (os->psize > 0)
     134         183 :         os->pduration = (p[0] >> 4) & 1;
     135             : 
     136         183 :     return 0;
     137             : }
     138             : 
     139             : const struct ogg_codec ff_vp8_codec = {
     140             :     .magic     = "OVP80",
     141             :     .magicsize = 5,
     142             :     .header    = vp8_header,
     143             :     .packet    = vp8_packet,
     144             :     .gptopts   = vp8_gptopts,
     145             :     .nb_header = 1,
     146             : };

Generated by: LCOV version 1.13