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