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.
27 #include "libavutil/bswap.h"
29 #include "libavcodec/bitstream.h"
35 typedef struct TheoraParams {
41 static int theora_header(AVFormatContext *s, int idx)
43 struct ogg *ogg = s->priv_data;
44 struct ogg_stream *os = ogg->streams + idx;
45 AVStream *st = s->streams[idx];
46 TheoraParams *thp = os->private;
47 int cds = st->codecpar->extradata_size + os->psize + 2;
51 if (!(os->buf[os->pstart] & 0x80))
55 thp = av_mallocz(sizeof(*thp));
57 return AVERROR(ENOMEM);
61 switch (os->buf[os->pstart]) {
66 bitstream_init(&bc, os->buf + os->pstart, os->psize * 8);
69 bitstream_skip(&bc, 7 * 8);
71 thp->version = bitstream_read(&bc, 24);
72 if (thp->version < 0x030100) {
73 av_log(s, AV_LOG_ERROR,
74 "Too old or unsupported Theora (%x)\n", thp->version);
75 return AVERROR(ENOSYS);
78 st->codecpar->width = bitstream_read(&bc, 16) << 4;
79 st->codecpar->height = bitstream_read(&bc, 16) << 4;
81 if (thp->version >= 0x030400)
82 bitstream_skip(&bc, 100);
84 if (thp->version >= 0x030200) {
85 int width = bitstream_read(&bc, 24);
86 int height = bitstream_read(&bc, 24);
87 if (width <= st->codecpar->width && width > st->codecpar->width - 16 &&
88 height <= st->codecpar->height && height > st->codecpar->height - 16) {
89 st->codecpar->width = width;
90 st->codecpar->height = height;
93 bitstream_skip(&bc, 16);
96 timebase.den = bitstream_read(&bc, 32);
97 timebase.num = bitstream_read(&bc, 32);
98 if (!(timebase.num > 0 && timebase.den > 0)) {
99 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
103 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
105 st->sample_aspect_ratio.num = bitstream_read(&bc, 24);
106 st->sample_aspect_ratio.den = bitstream_read(&bc, 24);
108 if (thp->version >= 0x030200)
109 bitstream_skip(&bc, 38);
110 if (thp->version >= 0x304000)
111 bitstream_skip(&bc, 2);
113 thp->gpshift = bitstream_read(&bc, 5);
114 thp->gpmask = (1 << thp->gpshift) - 1;
116 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
117 st->codecpar->codec_id = AV_CODEC_ID_THEORA;
118 st->need_parsing = AVSTREAM_PARSE_HEADERS;
122 ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 7, os->psize - 7);
125 return AVERROR_INVALIDDATA;
128 return AVERROR_INVALIDDATA;
131 if ((err = av_reallocp(&st->codecpar->extradata,
132 cds + AV_INPUT_BUFFER_PADDING_SIZE)) < 0) {
133 st->codecpar->extradata_size = 0;
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;
145 static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
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;
154 return AV_NOPTS_VALUE;
156 iframe = gp >> thp->gpshift;
157 pframe = gp & thp->gpmask;
159 if (thp->version < 0x030201)
163 os->pflags |= AV_PKT_FLAG_KEY;
166 *dts = iframe + pframe;
168 return iframe + pframe;
171 const struct ogg_codec ff_theora_codec = {
172 .magic = "\200theora",
174 .header = theora_header,
175 .gptopts = theora_gptopts,