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