]> git.sesse.net Git - ffmpeg/blob - libavformat/oggparsetheora.c
Merge commit 'b452d5ae866942cec00aa1432fe29498b38b49fc'
[ffmpeg] / libavformat / oggparsetheora.c
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
32 typedef struct TheoraParams {
33     int gpshift;
34     int gpmask;
35     unsigned version;
36 } TheoraParams;
37
38 static 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->codec->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_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);
73         }
74
75         st->codec->width  = get_bits(&gb, 16) << 4;
76         st->codec->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_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;
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_long(&gb, 24);
103         st->sample_aspect_ratio.den = get_bits_long(&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  = (1 << thp->gpshift) - 1;
112
113         st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
114         st->codec->codec_id   = AV_CODEC_ID_THEORA;
115         st->need_parsing      = AVSTREAM_PARSE_HEADERS;
116     }
117     break;
118     case 0x81:
119         ff_vorbis_comment(s, &st->metadata, 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->codec->extradata,
130                            cds + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) {
131         st->codec->extradata_size = 0;
132         return err;
133     }
134     cdp    = st->codec->extradata + st->codec->extradata_size;
135     *cdp++ = os->psize >> 8;
136     *cdp++ = os->psize & 0xff;
137     memcpy(cdp, os->buf + os->pstart, os->psize);
138     st->codec->extradata_size = cds;
139
140     return 1;
141 }
142
143 static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
144                                int64_t *dts)
145 {
146     struct ogg *ogg       = ctx->priv_data;
147     struct ogg_stream *os = ogg->streams + idx;
148     TheoraParams *thp     = os->private;
149     uint64_t iframe, pframe;
150
151     if (!thp)
152         return AV_NOPTS_VALUE;
153
154     iframe = gp >> thp->gpshift;
155     pframe = gp & thp->gpmask;
156
157     if (thp->version < 0x030201)
158         iframe++;
159
160     if (!pframe)
161         os->pflags |= AV_PKT_FLAG_KEY;
162
163     if (dts)
164         *dts = iframe + pframe;
165
166     return iframe + pframe;
167 }
168
169 static int theora_packet(AVFormatContext *s, int idx)
170 {
171     struct ogg *ogg = s->priv_data;
172     struct ogg_stream *os = ogg->streams + idx;
173     int duration;
174
175     /* first packet handling
176        here we parse the duration of each packet in the first page and compare
177        the total duration to the page granule to find the encoder delay and
178        set the first timestamp */
179
180     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
181         int seg;
182
183         duration = 1;
184         for (seg = os->segp; seg < os->nsegs; seg++) {
185             if (os->segments[seg] < 255)
186                 duration ++;
187         }
188
189         os->lastpts = os->lastdts   = theora_gptopts(s, idx, os->granule, NULL) - duration;
190         if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
191             s->streams[idx]->start_time = os->lastpts;
192             if (s->streams[idx]->duration)
193                 s->streams[idx]->duration -= s->streams[idx]->start_time;
194         }
195     }
196
197     /* parse packet duration */
198     if (os->psize > 0) {
199         os->pduration = 1;
200     }
201
202     return 0;
203 }
204
205 const struct ogg_codec ff_theora_codec = {
206     .magic     = "\200theora",
207     .magicsize = 7,
208     .header    = theora_header,
209     .packet    = theora_packet,
210     .gptopts   = theora_gptopts,
211     .nb_header = 3,
212 };