• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/oggparsetheora.c

Go to the documentation of this file.
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); /* 0x80"theora" */
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 };
Generated on Sun Apr 22 2012 21:54:08 for Libav by doxygen 1.7.1