2 * Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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.
26 #include "libavutil/bswap.h"
27 #include "libavcodec/get_bits.h"
32 typedef struct TheoraParams {
38 static int theora_header(AVFormatContext *s, int idx)
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->codec->extradata_size + os->psize + 2;
48 if (!(os->buf[os->pstart] & 0x80))
52 thp = av_mallocz(sizeof(*thp));
54 return AVERROR(ENOMEM);
58 switch (os->buf[os->pstart]) {
63 init_get_bits(&gb, os->buf + os->pstart, os->psize * 8);
66 skip_bits_long(&gb, 7 * 8);
68 thp->version = get_bits_long(&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);
75 st->codec->width = get_bits(&gb, 16) << 4;
76 st->codec->height = get_bits(&gb, 16) << 4;
78 if (thp->version >= 0x030400)
81 if (thp->version >= 0x030200) {
82 int width = get_bits_long(&gb, 24);
83 int height = get_bits_long(&gb, 24);
84 if (width <= st->codec->width && width > st->codec->width - 16 &&
85 height <= st->codec->height && height > st->codec->height - 16) {
86 st->codec->width = width;
87 st->codec->height = height;
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");
100 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
102 st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
103 st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
105 if (thp->version >= 0x030200)
106 skip_bits_long(&gb, 38);
107 if (thp->version >= 0x304000)
110 thp->gpshift = get_bits(&gb, 5);
111 thp->gpmask = (1 << thp->gpshift) - 1;
113 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
114 st->codec->codec_id = AV_CODEC_ID_THEORA;
115 st->need_parsing = AVSTREAM_PARSE_HEADERS;
119 ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 7, os->psize - 7);
122 return AVERROR_INVALIDDATA;
125 return AVERROR_INVALIDDATA;
128 if ((err = av_reallocp(&st->codec->extradata,
129 cds + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) {
130 st->codec->extradata_size = 0;
133 cdp = st->codec->extradata + st->codec->extradata_size;
134 *cdp++ = os->psize >> 8;
135 *cdp++ = os->psize & 0xff;
136 memcpy(cdp, os->buf + os->pstart, os->psize);
137 st->codec->extradata_size = cds;
142 static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
145 struct ogg *ogg = ctx->priv_data;
146 struct ogg_stream *os = ogg->streams + idx;
147 TheoraParams *thp = os->private;
148 uint64_t iframe, pframe;
151 return AV_NOPTS_VALUE;
153 iframe = gp >> thp->gpshift;
154 pframe = gp & thp->gpmask;
156 if (thp->version < 0x030201)
160 os->pflags |= AV_PKT_FLAG_KEY;
163 *dts = iframe + pframe;
165 return iframe + pframe;
168 const struct ogg_codec ff_theora_codec = {
169 .magic = "\200theora",
171 .header = theora_header,
172 .gptopts = theora_gptopts,