00001
00025 #include <stdlib.h>
00026 #include "libavutil/bswap.h"
00027 #include "libavcodec/bitstream.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(&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 st->time_base = st->codec->time_base;
00090
00091 st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
00092 st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
00093
00094 if (thp->version >= 0x030200)
00095 skip_bits(&gb, 38);
00096 if (thp->version >= 0x304000)
00097 skip_bits(&gb, 2);
00098
00099 thp->gpshift = get_bits(&gb, 5);
00100 thp->gpmask = (1 << thp->gpshift) - 1;
00101
00102 st->codec->codec_type = CODEC_TYPE_VIDEO;
00103 st->codec->codec_id = CODEC_ID_THEORA;
00104
00105 } else if (os->buf[os->pstart] == 0x83) {
00106 vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
00107 }
00108
00109 st->codec->extradata = av_realloc (st->codec->extradata, cds);
00110 cdp = st->codec->extradata + st->codec->extradata_size;
00111 *cdp++ = os->psize >> 8;
00112 *cdp++ = os->psize & 0xff;
00113 memcpy (cdp, os->buf + os->pstart, os->psize);
00114 st->codec->extradata_size = cds;
00115
00116 return 1;
00117 }
00118
00119 static uint64_t
00120 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
00121 {
00122 struct ogg *ogg = ctx->priv_data;
00123 struct ogg_stream *os = ogg->streams + idx;
00124 struct theora_params *thp = os->private;
00125 uint64_t iframe = gp >> thp->gpshift;
00126 uint64_t pframe = gp & thp->gpmask;
00127
00128 if (thp->version < 0x030201)
00129 iframe++;
00130
00131 if(!pframe)
00132 os->pflags |= PKT_FLAG_KEY;
00133
00134 return iframe + pframe;
00135 }
00136
00137 const struct ogg_codec ff_theora_codec = {
00138 .magic = "\200theora",
00139 .magicsize = 7,
00140 .header = theora_header,
00141 .gptopts = theora_gptopts
00142 };