FFmpeg
Loading...
Searching...
No Matches
theora.c
Go to the documentation of this file.
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>
27#include "libavutil/mem.h"
28#include "libavcodec/get_bits.h"
33
41
42typedef struct TheoraParams {
44 int gpmask;
45 unsigned version;
46 uint8_t *packet[3]; ///< headers of the link, until all three are in
47 int len[3];
48 enum TheoraPacketType last_packet; ///< type of the last packet seen by theora_packet()
50
51/**
52 * Pack the three headers of a link with Xiph lacing, which carries headers
53 * of any size, and free them.
54 */
55static int theora_pack_headers(TheoraParams *thp, uint8_t **buf)
56{
57 uint64_t size = 1 + thp->len[0] / 255 + 1 + thp->len[1] / 255 + 1 +
58 (uint64_t)thp->len[0] + thp->len[1] + thp->len[2];
59 int offset;
60 uint8_t *ptr;
61
62 if (size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)
64
66 if (!ptr)
67 return AVERROR(ENOMEM);
68
69 ptr[0] = 2;
70 offset = 1;
71 offset += av_xiphlacing(&ptr[offset], thp->len[0]);
72 offset += av_xiphlacing(&ptr[offset], thp->len[1]);
73 for (int i = 0; i < 3; i++) {
74 memcpy(&ptr[offset], thp->packet[i], thp->len[i]);
75 offset += thp->len[i];
76 av_freep(&thp->packet[i]);
77 }
78 return offset;
79}
80
81static int theora_header(AVFormatContext *s, int idx)
82{
83 struct ogg *ogg = s->priv_data;
84 struct ogg_stream *os = ogg->streams + idx;
85 AVStream *st = s->streams[idx];
86 TheoraParams *thp = os->private;
87 int type = os->buf[os->pstart] & 0x7f;
88 int ret;
89
90 if (!(os->buf[os->pstart] & 0x80))
91 return 0;
92
93 if (!thp) {
94 thp = av_mallocz(sizeof(*thp));
95 if (!thp)
96 return AVERROR(ENOMEM);
97 os->private = thp;
98 }
99
100 switch (os->buf[os->pstart]) {
101 case 0x80: {
102 GetBitContext gb;
103 AVRational timebase;
104
105 init_get_bits(&gb, os->buf + os->pstart, os->psize * 8);
106
107 /* 0x80"theora" */
108 skip_bits_long(&gb, 7 * 8);
109
110 thp->version = get_bits(&gb, 24);
111 if (thp->version < 0x030100) {
113 "Too old or unsupported Theora (%x)\n", thp->version);
114 return AVERROR(ENOSYS);
115 }
116
117 st->codecpar->width = get_bits(&gb, 16) << 4;
118 st->codecpar->height = get_bits(&gb, 16) << 4;
119
120 if (thp->version >= 0x030400)
121 skip_bits(&gb, 100);
122
123 if (thp->version >= 0x030200) {
124 int width = get_bits(&gb, 24);
125 int height = get_bits(&gb, 24);
126 if (width <= st->codecpar->width && width > st->codecpar->width - 16 &&
127 height <= st->codecpar->height && height > st->codecpar->height - 16) {
128 st->codecpar->width = width;
129 st->codecpar->height = height;
130 }
131
132 skip_bits(&gb, 16);
133 }
134
135 timebase.den = get_bits_long(&gb, 32);
136 timebase.num = get_bits_long(&gb, 32);
137 if (!(timebase.num > 0 && timebase.den > 0)) {
138 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
139 timebase.num = 1;
140 timebase.den = 25;
141 }
142 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
143
144 st->sample_aspect_ratio.num = get_bits(&gb, 24);
145 st->sample_aspect_ratio.den = get_bits(&gb, 24);
146
147 if (thp->version >= 0x030200)
148 skip_bits_long(&gb, 38);
149 if (thp->version >= 0x304000)
150 skip_bits(&gb, 2);
151
152 thp->gpshift = get_bits(&gb, 5);
153 thp->gpmask = (1U << thp->gpshift) - 1;
154
158 }
159 break;
160 case 0x81:
161 ff_vorbis_comment_read_stream(s, st, os->buf + os->pstart + 7, os->psize - 7);
163 case 0x82:
164 if (!thp->version)
165 return AVERROR_INVALIDDATA;
166 break;
167 default:
168 av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
169 return AVERROR_INVALIDDATA;
170 }
171
172 /* The headers are freed once packed, so a repeated one is ignored. */
173 if (type > 0 && !thp->packet[0] || type > 1 && !thp->packet[1])
174 return 1;
175
176 ret = av_reallocp(&thp->packet[type], os->psize);
177 if (ret < 0)
178 return ret;
179 memcpy(thp->packet[type], os->buf + os->pstart, os->psize);
180 thp->len[type] = os->psize;
181
182 if (type == 2) {
185 if (ret < 0) {
186 st->codecpar->extradata_size = 0;
187 return ret;
188 }
190 }
191
192 return 1;
193}
194
195static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp,
196 int64_t *dts)
197{
198 struct ogg *ogg = ctx->priv_data;
199 struct ogg_stream *os = ogg->streams + idx;
200 TheoraParams *thp = os->private;
201 uint64_t iframe, pframe;
202
203 if (!thp)
204 return AV_NOPTS_VALUE;
205
206 iframe = gp >> thp->gpshift;
207 pframe = gp & thp->gpmask;
208
209 if (thp->version < 0x030201)
210 iframe++;
211
212 if (!pframe)
213 os->pflags |= AV_PKT_FLAG_KEY;
214
215 if (dts)
216 *dts = iframe + pframe;
217
218 return iframe + pframe;
219}
220
221static enum TheoraPacketType theora_packet_type(const struct ogg_stream *os)
222{
223 uint8_t type = os->psize > 0 ? os->buf[os->pstart] : 0;
224
225 if (!(type & 0x80))
226 return THEORA_PACKET_DATA;
227 return type <= 0x82 ? THEORA_PACKET_ID + (type & 0x7f) : THEORA_PACKET_RESERVED;
228}
229
232{
233 enum TheoraPacketType last = thp->last_packet;
234 const char *error = NULL;
235
236 switch (type) {
238 return 0;
240 if (last == THEORA_PACKET_ID || last == THEORA_PACKET_COMMENT)
241 error = "data packet before the setup header";
242 break;
243 case THEORA_PACKET_ID:
244 if (last == THEORA_PACKET_ID || last == THEORA_PACKET_COMMENT)
245 error = "identification header before the setup header";
246 break;
248 if (last != THEORA_PACKET_ID)
249 error = "comment header without identification header";
250 break;
252 if (last != THEORA_PACKET_COMMENT)
253 error = "setup header without comment header";
254 break;
255 }
256
257 if (error)
259 "Invalid chained stream headers: %s, discarding them\n", error);
260
261 if (error || type == THEORA_PACKET_ID)
262 for (int i = 0; i < 3; i++)
263 av_freep(&thp->packet[i]);
264
266 return error ? AVERROR_INVALIDDATA : 0;
267}
268
269static int theora_packet(AVFormatContext *s, int idx)
270{
271 struct ogg *ogg = s->priv_data;
272 struct ogg_stream *os = ogg->streams + idx;
273 TheoraParams *thp = os->private;
275 int duration, ret;
276
277 /* A later link's headers are skipped and attached as extradata to the
278 * first data packet that follows. That packet keeps its timestamp, which
279 * ogg_read_packet() would clear after a stream replacement. */
281 int i = type - THEORA_PACKET_ID;
282
283 os->replace = 0;
284
286 return 1;
287
288 ret = av_reallocp(&thp->packet[i], os->psize);
289 if (ret < 0)
290 return ret;
291 memcpy(thp->packet[i], os->buf + os->pstart, os->psize);
292 thp->len[i] = os->psize;
293
294 if (type == THEORA_PACKET_COMMENT && os->psize > 7) {
295 ret = ff_vorbis_update_metadata(s, s->streams[idx],
296 os->buf + os->pstart + 7, os->psize - 7);
298 av_log(s, AV_LOG_WARNING, "Invalid Theora comment header, metadata ignored\n");
299 else if (ret < 0)
300 return ret;
301 }
302
303 if (thp->packet[0] && thp->packet[1] && thp->packet[2]) {
306 if (ret < 0) {
307 os->new_extradata_size = 0;
308 return ret;
309 }
311 }
312
313 return 1;
314 }
316
317 /* first packet handling
318 here we parse the duration of each packet in the first page and compare
319 the total duration to the page granule to find the encoder delay and
320 set the first timestamp */
321
322 if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
323 int seg;
324 int64_t pts;
325
326 duration = 1;
327 for (seg = os->segp; seg < os->nsegs; seg++) {
328 if (os->segments[seg] < 255)
329 duration ++;
330 }
331
332 pts = theora_gptopts(s, idx, os->granule, NULL);
333 if (pts != AV_NOPTS_VALUE)
335 os->lastpts = os->lastdts = pts;
336 if(s->streams[idx]->start_time == AV_NOPTS_VALUE && os->lastpts != AV_NOPTS_VALUE) {
337 s->streams[idx]->start_time = os->lastpts;
338 if (s->streams[idx]->duration > 0)
339 s->streams[idx]->duration = av_sat_sub64(s->streams[idx]->duration, s->streams[idx]->start_time);
340 }
341 }
342
343 /* parse packet duration */
344 if (os->psize > 0) {
345 os->pduration = 1;
346 }
347
348 return 0;
349}
350
351static void theora_cleanup(AVFormatContext *s, int idx)
352{
353 struct ogg *ogg = s->priv_data;
354 TheoraParams *thp = ogg->streams[idx].private;
355
356 if (thp)
357 for (int i = 0; i < 3; i++)
358 av_freep(&thp->packet[i]);
359}
360
362 .magic = "\200theora",
363 .magicsize = 7,
364 .header = theora_header,
365 .packet = theora_packet,
366 .gptopts = theora_gptopts,
367 .cleanup = theora_cleanup,
368 .nb_header = 3,
369};
static AVFormatContext * ctx
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition avformat.c:865
Main libavformat public API header.
@ AVSTREAM_PARSE_HEADERS
Only parse headers, do not repack.
Definition avformat.h:614
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
int ff_vorbis_comment_read_stream(AVFormatContext *as, AVStream *st, const uint8_t *buf, int size)
Parse Vorbis comments and add metadata to an AVStream.
Definition reader.c:73
#define av_sat_sub64
Definition common.h:142
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
unsigned int av_xiphlacing(unsigned char *s, unsigned int v)
Encode extradata length to a buffer.
Definition utils.c:847
static int64_t duration
Definition ffplay.c:359
int ret
Definition ffplay.c:391
bitstream reader API header.
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition get_bits.h:424
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition get_bits.h:280
static void skip_bits(GetBitContext *s, int n)
Definition get_bits.h:383
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition get_bits.h:337
static int init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size)
Initialize GetBitContext.
Definition get_bits.h:517
@ AV_CODEC_ID_THEORA
Definition codec_id.h:80
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition packet.h:657
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition mem.c:289
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
enum MPFType type
Definition jpegmpfenc.c:55
unsigned offset
Definition libaomenc.c:763
static av_always_inline FFStream * ffstream(AVStream *st)
Definition internal.h:390
Macro definitions for various function/variable attributes.
#define av_fallthrough
Definition attributes.h:67
int ff_vorbis_update_metadata(AVFormatContext *s, AVStream *st, const uint8_t *buf, int size)
Parse Vorbis comments, add metadata to an AVStream.
Definition vorbis.c:125
#define OGG_FLAG_EOS
Definition mapping.h:123
const struct ogg_codec ff_theora_codec
Definition theora.c:361
Memory handling functions.
int extradata_size
Size of the extradata content in bytes.
Definition codec_par.h:75
int height
The height of the video frame in pixels.
Definition codec_par.h:150
int width
The width of the video frame in pixels.
Definition codec_par.h:143
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
Format I/O context.
Definition avformat.h:1401
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
Stream structure.
Definition avformat.h:768
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:791
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition avformat.h:846
enum AVStreamParseType need_parsing
Definition internal.h:346
int len[3]
Definition theora.c:47
uint8_t * packet[3]
headers of the link, until all three are in
Definition theora.c:46
int gpmask
Definition theora.c:44
int gpshift
Definition theora.c:43
enum TheoraPacketType last_packet
type of the last packet seen by theora_packet()
Definition theora.c:48
unsigned version
Definition theora.c:45
Copyright (C) 2005 Michael Ahlberg, Måns Rullgård.
Definition mapping.h:30
unsigned int pduration
Definition mapping.h:74
uint8_t * new_extradata
Definition mapping.h:99
size_t new_extradata_size
Definition mapping.h:100
unsigned int pflags
Definition mapping.h:73
int nsegs
Definition mapping.h:85
uint8_t segments[255]
Definition mapping.h:86
uint64_t granule
Definition mapping.h:76
int64_t lastdts
Definition mapping.h:79
unsigned int pstart
Definition mapping.h:71
int replace
Definition mapping.h:96
unsigned int psize
Definition mapping.h:72
void * private
Definition mapping.h:101
uint8_t * buf
Definition mapping.h:68
int64_t lastpts
Definition mapping.h:78
int segp
Definition mapping.h:85
int flags
Definition mapping.h:82
Definition mapping.h:112
struct ogg_stream * streams
Definition mapping.h:113
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static void error(const char *err)
#define height
Definition dsp.h:99
#define width
Definition dsp.h:99
static int theora_packet(AVFormatContext *s, int idx)
Definition theora.c:269
static enum TheoraPacketType theora_packet_type(const struct ogg_stream *os)
Definition theora.c:221
static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
Definition theora.c:195
static int theora_pack_headers(TheoraParams *thp, uint8_t **buf)
Pack the three headers of a link with Xiph lacing, which carries headers of any size,...
Definition theora.c:55
static int theora_check_packet_order(AVFormatContext *s, TheoraParams *thp, enum TheoraPacketType type)
Definition theora.c:230
static void theora_cleanup(AVFormatContext *s, int idx)
Definition theora.c:351
TheoraPacketType
Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi.
Definition theora.c:34
@ THEORA_PACKET_COMMENT
Definition theora.c:37
@ THEORA_PACKET_RESERVED
Definition theora.c:39
@ THEORA_PACKET_SETUP
Definition theora.c:38
@ THEORA_PACKET_DATA
Definition theora.c:35
@ THEORA_PACKET_ID
Definition theora.c:36
static int theora_header(AVFormatContext *s, int idx)
Definition theora.c:81
static int64_t pts
int size