00001
00025 #include <stdlib.h>
00026 #include "avformat.h"
00027 #include "bitstream.h"
00028 #include "bswap.h"
00029 #include "oggdec.h"
00030
00031 typedef struct theora_params {
00032 int gpshift;
00033 int gpmask;
00034 } theora_params_t;
00035
00036 static int
00037 theora_header (AVFormatContext * s, int idx)
00038 {
00039 ogg_t *ogg = s->priv_data;
00040 ogg_stream_t *os = ogg->streams + idx;
00041 AVStream *st = s->streams[idx];
00042 theora_params_t *thp = os->private;
00043 int cds = st->codec->extradata_size + os->psize + 2;
00044 uint8_t *cdp;
00045
00046 if(!(os->buf[os->pstart] & 0x80))
00047 return 0;
00048
00049 if(!thp){
00050 thp = av_mallocz(sizeof(*thp));
00051 os->private = thp;
00052 }
00053
00054 if (os->buf[os->pstart] == 0x80) {
00055 GetBitContext gb;
00056 int width, height;
00057 int version;
00058
00059 init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
00060
00061 skip_bits(&gb, 7*8);
00062
00063 version = get_bits_long(&gb, 24);
00064 if (version < 0x030100)
00065 {
00066 av_log(s, AV_LOG_ERROR,
00067 "Too old or unsupported Theora (%x)\n", 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 (version >= 0x030400)
00076 skip_bits(&gb, 100);
00077
00078 width = get_bits_long(&gb, 24);
00079 height = get_bits_long(&gb, 24);
00080 if ( width <= st->codec->width && width > st->codec->width-16
00081 && height <= st->codec->height && height > st->codec->height-16)
00082 avcodec_set_dimensions(st->codec, width, height);
00083
00084 if (version >= 0x030200)
00085 skip_bits(&gb, 16);
00086 st->codec->time_base.den = get_bits_long(&gb, 32);
00087 st->codec->time_base.num = get_bits_long(&gb, 32);
00088 st->time_base = st->codec->time_base;
00089
00090 st->codec->sample_aspect_ratio.num = get_bits_long(&gb, 24);
00091 st->codec->sample_aspect_ratio.den = get_bits_long(&gb, 24);
00092
00093 if (version >= 0x030200)
00094 skip_bits(&gb, 38);
00095 if (version >= 0x304000)
00096 skip_bits(&gb, 2);
00097
00098 thp->gpshift = get_bits(&gb, 5);
00099 thp->gpmask = (1 << thp->gpshift) - 1;
00100
00101 st->codec->codec_type = CODEC_TYPE_VIDEO;
00102 st->codec->codec_id = CODEC_ID_THEORA;
00103
00104 } else if (os->buf[os->pstart] == 0x83) {
00105 vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
00106 }
00107
00108 st->codec->extradata = av_realloc (st->codec->extradata, cds);
00109 cdp = st->codec->extradata + st->codec->extradata_size;
00110 *cdp++ = os->psize >> 8;
00111 *cdp++ = os->psize & 0xff;
00112 memcpy (cdp, os->buf + os->pstart, os->psize);
00113 st->codec->extradata_size = cds;
00114
00115 return 1;
00116 }
00117
00118 static uint64_t
00119 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp)
00120 {
00121 ogg_t *ogg = ctx->priv_data;
00122 ogg_stream_t *os = ogg->streams + idx;
00123 theora_params_t *thp = os->private;
00124 uint64_t iframe = gp >> thp->gpshift;
00125 uint64_t pframe = gp & thp->gpmask;
00126
00127 if(!pframe)
00128 os->pflags |= PKT_FLAG_KEY;
00129
00130 return iframe + pframe;
00131 }
00132
00133 ogg_codec_t theora_codec = {
00134 .magic = "\200theora",
00135 .magicsize = 7,
00136 .header = theora_header,
00137 .gptopts = theora_gptopts
00138 };