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 AVRational timebase;
00060
00061 init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
00062
00063 skip_bits_long(&gb, 7*8);
00064
00065 thp->version = get_bits_long(&gb, 24);
00066 if (thp->version < 0x030100)
00067 {
00068 av_log(s, AV_LOG_ERROR,
00069 "Too old or unsupported Theora (%x)\n", thp->version);
00070 return -1;
00071 }
00072
00073 width = get_bits(&gb, 16) << 4;
00074 height = get_bits(&gb, 16) << 4;
00075 avcodec_set_dimensions(st->codec, width, height);
00076
00077 if (thp->version >= 0x030400)
00078 skip_bits(&gb, 100);
00079
00080 if (thp->version >= 0x030200) {
00081 width = get_bits_long(&gb, 24);
00082 height = get_bits_long(&gb, 24);
00083 if ( width <= st->codec->width && width > st->codec->width-16
00084 && height <= st->codec->height && height > st->codec->height-16)
00085 avcodec_set_dimensions(st->codec, width, height);
00086
00087 skip_bits(&gb, 16);
00088 }
00089 timebase.den = get_bits_long(&gb, 32);
00090 timebase.num = get_bits_long(&gb, 32);
00091 if (!(timebase.num > 0 && timebase.den > 0)) {
00092 av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
00093 timebase.num = 1;
00094 timebase.den = 25;
00095 }
00096 avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
00097
00098 st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
00099 st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
00100
00101 if (thp->version >= 0x030200)
00102 skip_bits_long(&gb, 38);
00103 if (thp->version >= 0x304000)
00104 skip_bits(&gb, 2);
00105
00106 thp->gpshift = get_bits(&gb, 5);
00107 thp->gpmask = (1 << thp->gpshift) - 1;
00108
00109 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00110 st->codec->codec_id = CODEC_ID_THEORA;
00111 st->need_parsing = AVSTREAM_PARSE_HEADERS;
00112
00113 } else if (os->buf[os->pstart] == 0x83) {
00114 ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
00115 }
00116
00117 st->codec->extradata = av_realloc (st->codec->extradata,
00118 cds + FF_INPUT_BUFFER_PADDING_SIZE);
00119 cdp = st->codec->extradata + st->codec->extradata_size;
00120 *cdp++ = os->psize >> 8;
00121 *cdp++ = os->psize & 0xff;
00122 memcpy (cdp, os->buf + os->pstart, os->psize);
00123 st->codec->extradata_size = cds;
00124
00125 return 1;
00126 }
00127
00128 static uint64_t
00129 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
00130 {
00131 struct ogg *ogg = ctx->priv_data;
00132 struct ogg_stream *os = ogg->streams + idx;
00133 struct theora_params *thp = os->private;
00134 uint64_t iframe, pframe;
00135
00136 if (!thp)
00137 return AV_NOPTS_VALUE;
00138
00139 iframe = gp >> thp->gpshift;
00140 pframe = gp & thp->gpmask;
00141
00142 if (thp->version < 0x030201)
00143 iframe++;
00144
00145 if(!pframe)
00146 os->pflags |= AV_PKT_FLAG_KEY;
00147
00148 if (dts)
00149 *dts = iframe + pframe;
00150
00151 return iframe + pframe;
00152 }
00153
00154 static int theora_packet(AVFormatContext *s, int idx)
00155 {
00156 struct ogg *ogg = s->priv_data;
00157 struct ogg_stream *os = ogg->streams + idx;
00158 int duration;
00159
00160
00161
00162
00163
00164
00165 if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
00166 int seg;
00167
00168 duration = 1;
00169 for (seg = os->segp; seg < os->nsegs; seg++) {
00170 if (os->segments[seg] < 255)
00171 duration ++;
00172 }
00173
00174 os->lastpts = os->lastdts = theora_gptopts(s, idx, os->granule, NULL) - duration;
00175 if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
00176 s->streams[idx]->start_time = os->lastpts;
00177 if (s->streams[idx]->duration)
00178 s->streams[idx]->duration -= s->streams[idx]->start_time;
00179 }
00180 }
00181
00182
00183 if (os->psize > 0) {
00184 os->pduration = 1;
00185 }
00186
00187 return 0;
00188 }
00189
00190 const struct ogg_codec ff_theora_codec = {
00191 .magic = "\200theora",
00192 .magicsize = 7,
00193 .header = theora_header,
00194 .packet = theora_packet,
00195 .gptopts = theora_gptopts
00196 };