~ppsspp/ppsspp/ffmpeg-upstream

1 by Sérgio Benjamim
FFmpeg 2.7.1 source for ppsspp.
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
static int vp8_header(AVFormatContext *s, int idx)
31
{
32
    struct ogg *ogg = s->priv_data;
33
    struct ogg_stream *os = ogg->streams + idx;
34
    uint8_t *p = os->buf + os->pstart;
35
    AVStream *st = s->streams[idx];
36
    AVRational framerate;
37
38
    if (os->psize < 7 || p[0] != 0x4f)
39
        return 0;
40
41
    switch (p[5]){
42
    case 0x01:
43
        if (os->psize < VP8_HEADER_SIZE) {
44
            av_log(s, AV_LOG_ERROR, "Invalid OggVP8 header packet");
45
            return AVERROR_INVALIDDATA;
46
        }
47
48
        if (p[6] != 1) {
49
            av_log(s, AV_LOG_WARNING,
50
                   "Unknown OggVP8 version %d.%d\n", p[6], p[7]);
51
            return AVERROR_INVALIDDATA;
52
        }
53
54
        st->codec->width            = AV_RB16(p +  8);
55
        st->codec->height           = AV_RB16(p + 10);
56
        st->sample_aspect_ratio.num = AV_RB24(p + 12);
57
        st->sample_aspect_ratio.den = AV_RB24(p + 15);
58
        framerate.num               = AV_RB32(p + 18);
59
        framerate.den               = AV_RB32(p + 22);
60
61
        avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
62
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
63
        st->codec->codec_id   = AV_CODEC_ID_VP8;
64
        st->need_parsing      = AVSTREAM_PARSE_HEADERS;
65
        break;
66
    case 0x02:
67
        if (p[6] != 0x20)
68
            return AVERROR_INVALIDDATA;
69
        ff_vorbis_stream_comment(s, st, p + 7, os->psize - 7);
70
        break;
71
    default:
72
        av_log(s, AV_LOG_ERROR, "Unknown VP8 header type 0x%02X\n", p[5]);
73
        return AVERROR_INVALIDDATA;
74
    }
75
76
    return 1;
77
}
78
79
static uint64_t vp8_gptopts(AVFormatContext *s, int idx,
80
                            uint64_t granule, int64_t *dts)
81
{
82
    struct ogg *ogg = s->priv_data;
83
    struct ogg_stream *os = ogg->streams + idx;
84
85
    uint64_t pts  = (granule >> 32);
86
    uint32_t dist = (granule >>  3) & 0x07ffffff;
87
88
    if (!dist)
89
        os->pflags |= AV_PKT_FLAG_KEY;
90
91
    if (dts)
92
        *dts = pts;
93
94
    return pts;
95
}
96
97
static int vp8_packet(AVFormatContext *s, int idx)
98
{
99
    struct ogg *ogg = s->priv_data;
100
    struct ogg_stream *os = ogg->streams + idx;
101
    uint8_t *p = os->buf + os->pstart;
102
103
    if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) &&
104
        !(os->flags & OGG_FLAG_EOS)) {
105
        int seg;
106
        int duration;
107
        uint8_t *last_pkt = p;
108
        uint8_t *next_pkt;
109
110
        seg = os->segp;
111
        duration = (last_pkt[0] >> 4) & 1;
112
        next_pkt = last_pkt += os->psize;
113
        for (; seg < os->nsegs; seg++) {
114
            if (os->segments[seg] < 255) {
115
                duration += (last_pkt[0] >> 4) & 1;
116
                last_pkt  = next_pkt + os->segments[seg];
117
            }
118
            next_pkt += os->segments[seg];
119
        }
120
        os->lastpts =
121
        os->lastdts = vp8_gptopts(s, idx, os->granule, NULL) - duration;
122
        if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
123
            s->streams[idx]->start_time = os->lastpts;
124
            if (s->streams[idx]->duration)
125
                s->streams[idx]->duration -= s->streams[idx]->start_time;
126
        }
127
    }
128
129
    if (os->psize > 0)
130
        os->pduration = (p[0] >> 4) & 1;
131
132
    return 0;
133
}
134
135
const struct ogg_codec ff_vp8_codec = {
136
    .magic     = "OVP80",
137
    .magicsize = 5,
138
    .header    = vp8_header,
139
    .packet    = vp8_packet,
140
    .gptopts   = vp8_gptopts,
141
    .nb_header = 1,
142
};