00001
00025 #include <stdlib.h>
00026 #include "libavutil/bswap.h"
00027 #include "libavcodec/get_bits.h"
00028 #include "avformat.h"
00029 #include "oggdec.h"
00030
00031 struct theora_params {
00032 int gpshift;
00033 int gpmask;
00034 unsigned version;
00035 };
00036
00037 static int
00038 theora_header (AVFormatContext * s, int idx)
00039 {
00040 struct ogg *ogg = s->priv_data;
00041 struct ogg_stream *os = ogg->streams + idx;
00042 AVStream *st = s->streams[idx];
00043 struct theora_params *thp = os->private;
00044 int cds = st->codec->extradata_size + os->psize + 2;
00045 uint8_t *cdp;
00046
00047 if(!(os->buf[os->pstart] & 0x80))
00048 return 0;
00049
00050 if(!thp){
00051 thp = av_mallocz(sizeof(*thp));
00052 os->private = thp;
00053 }
00054
00055 if (os->buf[os->pstart] == 0x80) {
00056 GetBitContext gb;
00057 int width, height;
00058
00059 init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
00060
00061 skip_bits_long(&gb, 7*8);
00062
00063 thp->version = get_bits_long(&gb, 24);
00064 if (thp->version < 0x030100)
00065 {
00066 av_log(s, AV_LOG_ERROR,
00067 "Too old or unsupported Theora (%x)\n", thp->version);
00068 return -1;
00069 }
00070
00071 width = get_bits(&gb, 16) << 4;
00072 height = get_bits(&gb, 16) << 4;
00073 avcodec_set_dimensions(st->codec, width, height);
00074
00075 if (thp->version >= 0x030400)
00076 skip_bits(&gb, 100);
00077
00078 if (thp->version >= 0x030200) {
00079 width = get_bits_long(&gb, 24);
00080 height = get_bits_long(&gb, 24);
00081 if ( width <= st->codec->width && width > st->codec->width-16
00082 && height <= st->codec->height && height > st->codec->height-16)
00083 avcodec_set_dimensions(st->codec, width, height);
00084
00085 skip_bits(&gb, 16);
00086 }
00087 st->codec->time_base.den = get_bits_long(&gb, 32);
00088 st->codec->time_base.num = get_bits_long(&gb, 32);
00089 if (!(st->codec->time_base.num > 0 && st->codec->time_base.den > 0)) {
00090 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
00091 st->codec->time_base.num = 1;
00092 st->codec->time_base.den = 25;
00093 }
00094 av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
00095
00096 st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
00097 st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
00098
00099 if (thp->version >= 0x030200)
00100 skip_bits_long(&gb, 38);
00101 if (thp->version >= 0x304000)
00102 skip_bits(&gb, 2);
00103
00104 thp->gpshift = get_bits(&gb, 5);
00105 thp->gpmask = (1 << thp->gpshift) - 1;
00106
00107 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00108 st->codec->codec_id = CODEC_ID_THEORA;
00109 st->need_parsing = AVSTREAM_PARSE_HEADERS;
00110
00111 } else if (os->buf[os->pstart] == 0x83) {
00112 ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
00113 }
00114
00115 st->codec->extradata = av_realloc (st->codec->extradata,
00116 cds + FF_INPUT_BUFFER_PADDING_SIZE);
00117 cdp = st->codec->extradata + st->codec->extradata_size;
00118 *cdp++ = os->psize >> 8;
00119 *cdp++ = os->psize & 0xff;
00120 memcpy (cdp, os->buf + os->pstart, os->psize);
00121 st->codec->extradata_size = cds;
00122
00123 return 1;
00124 }
00125
00126 static uint64_t
00127 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
00128 {
00129 struct ogg *ogg = ctx->priv_data;
00130 struct ogg_stream *os = ogg->streams + idx;
00131 struct theora_params *thp = os->private;
00132 uint64_t iframe = gp >> thp->gpshift;
00133 uint64_t pframe = gp & thp->gpmask;
00134
00135 if (thp->version < 0x030201)
00136 iframe++;
00137
00138 if(!pframe)
00139 os->pflags |= AV_PKT_FLAG_KEY;
00140
00141 if (dts)
00142 *dts = iframe + pframe;
00143
00144 return iframe + pframe;
00145 }
00146
00147 const struct ogg_codec ff_theora_codec = {
00148 .magic = "\200theora",
00149 .magicsize = 7,
00150 .header = theora_header,
00151 .gptopts = theora_gptopts
00152 };