X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Foggparsetheora.c;h=ed31d539d9f9f48877210dca2b55463d9b369340;hb=4a2ef39442bf7f0150db07a1fbfcf8286e4d44a3;hp=d1a4fdf9984e622ab51ef1c6ff8dce9522ab930c;hpb=cd34bc76174397712fc0b2502d550a45dd25c11c;p=ffmpeg diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index d1a4fdf9984..ed31d539d9f 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -24,22 +24,24 @@ #include #include "libavutil/bswap.h" -#include "libavcodec/bitstream.h" +#include "libavcodec/get_bits.h" #include "avformat.h" +#include "internal.h" #include "oggdec.h" -typedef struct theora_params { +struct theora_params { int gpshift; int gpmask; -} theora_params_t; + unsigned version; +}; static int theora_header (AVFormatContext * s, int idx) { - ogg_t *ogg = s->priv_data; - ogg_stream_t *os = ogg->streams + idx; + struct ogg *ogg = s->priv_data; + struct ogg_stream *os = ogg->streams + idx; AVStream *st = s->streams[idx]; - theora_params_t *thp = os->private; + struct theora_params *thp = os->private; int cds = st->codec->extradata_size + os->psize + 2; uint8_t *cdp; @@ -51,20 +53,21 @@ theora_header (AVFormatContext * s, int idx) os->private = thp; } - if (os->buf[os->pstart] == 0x80) { + switch (os->buf[os->pstart]) { + case 0x80: { GetBitContext gb; int width, height; - int version; + AVRational timebase; init_get_bits(&gb, os->buf + os->pstart, os->psize*8); - skip_bits(&gb, 7*8); /* 0x80"theora" */ + skip_bits_long(&gb, 7*8); /* 0x80"theora" */ - version = get_bits_long(&gb, 24); - if (version < 0x030100) + thp->version = get_bits_long(&gb, 24); + if (thp->version < 0x030100) { av_log(s, AV_LOG_ERROR, - "Too old or unsupported Theora (%x)\n", version); + "Too old or unsupported Theora (%x)\n", thp->version); return -1; } @@ -72,40 +75,56 @@ theora_header (AVFormatContext * s, int idx) height = get_bits(&gb, 16) << 4; avcodec_set_dimensions(st->codec, width, height); - if (version >= 0x030400) + if (thp->version >= 0x030400) skip_bits(&gb, 100); - width = get_bits_long(&gb, 24); - height = get_bits_long(&gb, 24); - if ( width <= st->codec->width && width > st->codec->width-16 - && height <= st->codec->height && height > st->codec->height-16) - avcodec_set_dimensions(st->codec, width, height); + if (thp->version >= 0x030200) { + width = get_bits_long(&gb, 24); + height = get_bits_long(&gb, 24); + if ( width <= st->codec->width && width > st->codec->width-16 + && height <= st->codec->height && height > st->codec->height-16) + avcodec_set_dimensions(st->codec, width, height); - if (version >= 0x030200) skip_bits(&gb, 16); - st->codec->time_base.den = get_bits_long(&gb, 32); - st->codec->time_base.num = get_bits_long(&gb, 32); - st->time_base = st->codec->time_base; + } + timebase.den = get_bits_long(&gb, 32); + timebase.num = get_bits_long(&gb, 32); + if (!(timebase.num > 0 && timebase.den > 0)) { + av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n"); + timebase.num = 1; + timebase.den = 25; + } + avpriv_set_pts_info(st, 64, timebase.num, timebase.den); st->sample_aspect_ratio.num = get_bits_long(&gb, 24); st->sample_aspect_ratio.den = get_bits_long(&gb, 24); - if (version >= 0x030200) - skip_bits(&gb, 38); - if (version >= 0x304000) + if (thp->version >= 0x030200) + skip_bits_long(&gb, 38); + if (thp->version >= 0x304000) skip_bits(&gb, 2); thp->gpshift = get_bits(&gb, 5); thp->gpmask = (1 << thp->gpshift) - 1; - st->codec->codec_type = CODEC_TYPE_VIDEO; - st->codec->codec_id = CODEC_ID_THEORA; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = AV_CODEC_ID_THEORA; + st->need_parsing = AVSTREAM_PARSE_HEADERS; - } else if (os->buf[os->pstart] == 0x83) { - vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8); + } + break; + case 0x81: + ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7); + case 0x82: + if (!thp->version) + return -1; + break; + default: + return -1; } - st->codec->extradata = av_realloc (st->codec->extradata, cds); + st->codec->extradata = av_realloc (st->codec->extradata, + cds + FF_INPUT_BUFFER_PADDING_SIZE); cdp = st->codec->extradata + st->codec->extradata_size; *cdp++ = os->psize >> 8; *cdp++ = os->psize & 0xff; @@ -116,23 +135,35 @@ theora_header (AVFormatContext * s, int idx) } static uint64_t -theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp) +theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts) { - ogg_t *ogg = ctx->priv_data; - ogg_stream_t *os = ogg->streams + idx; - theora_params_t *thp = os->private; - uint64_t iframe = gp >> thp->gpshift; - uint64_t pframe = gp & thp->gpmask; + struct ogg *ogg = ctx->priv_data; + struct ogg_stream *os = ogg->streams + idx; + struct theora_params *thp = os->private; + uint64_t iframe, pframe; + + if (!thp) + return AV_NOPTS_VALUE; + + iframe = gp >> thp->gpshift; + pframe = gp & thp->gpmask; + + if (thp->version < 0x030201) + iframe++; if(!pframe) - os->pflags |= PKT_FLAG_KEY; + os->pflags |= AV_PKT_FLAG_KEY; + + if (dts) + *dts = iframe + pframe; return iframe + pframe; } -const ogg_codec_t theora_codec = { +const struct ogg_codec ff_theora_codec = { .magic = "\200theora", .magicsize = 7, .header = theora_header, - .gptopts = theora_gptopts + .gptopts = theora_gptopts, + .nb_header = 3, };