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
32typedef struct TheoraParams {
33    int gpshift;
34    int gpmask;
35    unsigned version;
36} TheoraParams;
37
38static int theora_header(AVFormatContext *s, int idx)
39{
40    struct ogg *ogg       = s->priv_data;
41    struct ogg_stream *os = ogg->streams + idx;
42    AVStream *st          = s->streams[idx];
43    TheoraParams *thp     = os->private;
44    int cds               = st->codecpar->extradata_size + os->psize + 2;
45    int err;
46    uint8_t *cdp;
47
48    if (!(os->buf[os->pstart] & 0x80))
49        return 0;
50
51    if (!thp) {
52        thp = av_mallocz(sizeof(*thp));
53        if (!thp)
54            return AVERROR(ENOMEM);
55        os->private = thp;
56    }
57
58    switch (os->buf[os->pstart]) {
59    case 0x80: {
60        GetBitContext gb;
61        AVRational timebase;
62
63        init_get_bits(&gb, os->buf + os->pstart, os->psize * 8);
64
65        /* 0x80"theora" */
66        skip_bits_long(&gb, 7 * 8);
67
68        thp->version = get_bits(&gb, 24);
69        if (thp->version < 0x030100) {
70            av_log(s, AV_LOG_ERROR,
71                   "Too old or unsupported Theora (%x)\n", thp->version);
72            return AVERROR(ENOSYS);
73        }
74
75        st->codecpar->width  = get_bits(&gb, 16) << 4;
76        st->codecpar->height = get_bits(&gb, 16) << 4;
77
78        if (thp->version >= 0x030400)
79            skip_bits(&gb, 100);
80
81        if (thp->version >= 0x030200) {
82            int width  = get_bits(&gb, 24);
83            int height = get_bits(&gb, 24);
84            if (width  <= st->codecpar->width  && width  > st->codecpar->width  - 16 &&
85                height <= st->codecpar->height && height > st->codecpar->height - 16) {
86                st->codecpar->width  = width;
87                st->codecpar->height = height;
88            }
89
90            skip_bits(&gb, 16);
91        }
92
93        timebase.den = get_bits_long(&gb, 32);
94        timebase.num = get_bits_long(&gb, 32);
95        if (!(timebase.num > 0 && timebase.den > 0)) {
96            av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
97            timebase.num = 1;
98            timebase.den = 25;
99        }
100        avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
101
102        st->sample_aspect_ratio.num = get_bits(&gb, 24);
103        st->sample_aspect_ratio.den = get_bits(&gb, 24);
104
105        if (thp->version >= 0x030200)
106            skip_bits_long(&gb, 38);
107        if (thp->version >= 0x304000)
108            skip_bits(&gb, 2);
109
110        thp->gpshift = get_bits(&gb, 5);
111        thp->gpmask  = (1U << thp->gpshift) - 1;
112
113        st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
114        st->codecpar->codec_id   = AV_CODEC_ID_THEORA;
115        ffstream(st)->need_parsing = AVSTREAM_PARSE_HEADERS;
116    }
117    break;
118    case 0x81:
119        ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 7, os->psize - 7);
120    case 0x82:
121        if (!thp->version)
122            return AVERROR_INVALIDDATA;
123        break;
124    default:
125        av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
126        return AVERROR_INVALIDDATA;
127    }
128
129    if ((err = av_reallocp(&st->codecpar->extradata,
130                           cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
131        st->codecpar->extradata_size = 0;
132        return err;
133    }
134    memset(st->codecpar->extradata + cds, 0, AV_INPUT_BUFFER_PADDING_SIZE);
135
136    cdp    = st->codecpar->extradata + st->codecpar->extradata_size;
137    *cdp++ = os->psize >> 8;
138    *cdp++ = os->psize & 0xff;
139    memcpy(cdp, os->buf + os->pstart, os->psize);
140    st->codecpar->extradata_size = cds;
141
142    return 1;
143}
144
145static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
146                               int64_t *dts)
147{
148    struct ogg *ogg       = ctx->priv_data;
149    struct ogg_stream *os = ogg->streams + idx;
150    TheoraParams *thp     = os->private;
151    uint64_t iframe, pframe;
152
153    if (!thp)
154        return AV_NOPTS_VALUE;
155
156    iframe = gp >> thp->gpshift;
157    pframe = gp & thp->gpmask;
158
159    if (thp->version < 0x030201)
160        iframe++;
161
162    if (!pframe)
163        os->pflags |= AV_PKT_FLAG_KEY;
164
165    if (dts)
166        *dts = iframe + pframe;
167
168    return iframe + pframe;
169}
170
171static int theora_packet(AVFormatContext *s, int idx)
172{
173    struct ogg *ogg = s->priv_data;
174    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    if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
183        int seg;
184        int64_t pts;
185
186        duration = 1;
187        for (seg = os->segp; seg < os->nsegs; seg++) {
188            if (os->segments[seg] < 255)
189                duration ++;
190        }
191
192        pts = theora_gptopts(s, idx, os->granule, NULL);
193        if (pts != AV_NOPTS_VALUE)
194            pts = av_sat_sub64(pts, duration);
195        os->lastpts = os->lastdts = pts;
196        if(s->streams[idx]->start_time == AV_NOPTS_VALUE && os->lastpts != AV_NOPTS_VALUE) {
197            s->streams[idx]->start_time = os->lastpts;
198            if (s->streams[idx]->duration > 0)
199                s->streams[idx]->duration = av_sat_sub64(s->streams[idx]->duration, s->streams[idx]->start_time);
200        }
201    }
202
203    /* parse packet duration */
204    if (os->psize > 0) {
205        os->pduration = 1;
206    }
207
208    return 0;
209}
210
211const struct ogg_codec ff_theora_codec = {
212    .magic     = "\200theora",
213    .magicsize = 7,
214    .header    = theora_header,
215    .packet    = theora_packet,
216    .gptopts   = theora_gptopts,
217    .nb_header = 3,
218};
219