oggparsetheora.c
Go to the documentation of this file.
1 
25 #include <stdlib.h>
26 #include "libavutil/bswap.h"
27 #include "libavcodec/get_bits.h"
28 #include "avformat.h"
29 #include "internal.h"
30 #include "oggdec.h"
31 
32 struct theora_params {
33  int gpshift;
34  int gpmask;
35  unsigned version;
36 };
37 
38 static int
40 {
41  struct ogg *ogg = s->priv_data;
42  struct ogg_stream *os = ogg->streams + idx;
43  AVStream *st = s->streams[idx];
44  struct theora_params *thp = os->private;
45  int cds = st->codec->extradata_size + os->psize + 2;
46  uint8_t *cdp;
47 
48  if(!(os->buf[os->pstart] & 0x80))
49  return 0;
50 
51  if(!thp){
52  thp = av_mallocz(sizeof(*thp));
53  os->private = thp;
54  }
55 
56  if (os->buf[os->pstart] == 0x80) {
57  GetBitContext gb;
58  int width, height;
59 
60  init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
61 
62  skip_bits_long(&gb, 7*8); /* 0x80"theora" */
63 
64  thp->version = get_bits_long(&gb, 24);
65  if (thp->version < 0x030100)
66  {
68  "Too old or unsupported Theora (%x)\n", thp->version);
69  return -1;
70  }
71 
72  width = get_bits(&gb, 16) << 4;
73  height = get_bits(&gb, 16) << 4;
74  avcodec_set_dimensions(st->codec, width, height);
75 
76  if (thp->version >= 0x030400)
77  skip_bits(&gb, 100);
78 
79  if (thp->version >= 0x030200) {
80  width = get_bits_long(&gb, 24);
81  height = get_bits_long(&gb, 24);
82  if ( width <= st->codec->width && width > st->codec->width-16
83  && height <= st->codec->height && height > st->codec->height-16)
84  avcodec_set_dimensions(st->codec, width, height);
85 
86  skip_bits(&gb, 16);
87  }
88  st->codec->time_base.den = get_bits_long(&gb, 32);
89  st->codec->time_base.num = get_bits_long(&gb, 32);
90  if (!(st->codec->time_base.num > 0 && st->codec->time_base.den > 0)) {
91  av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
92  st->codec->time_base.num = 1;
93  st->codec->time_base.den = 25;
94  }
96 
97  st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
98  st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
99 
100  if (thp->version >= 0x030200)
101  skip_bits_long(&gb, 38);
102  if (thp->version >= 0x304000)
103  skip_bits(&gb, 2);
104 
105  thp->gpshift = get_bits(&gb, 5);
106  thp->gpmask = (1 << thp->gpshift) - 1;
107 
111 
112  } else if (os->buf[os->pstart] == 0x83) {
113  ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
114  }
115 
118  cdp = st->codec->extradata + st->codec->extradata_size;
119  *cdp++ = os->psize >> 8;
120  *cdp++ = os->psize & 0xff;
121  memcpy (cdp, os->buf + os->pstart, os->psize);
122  st->codec->extradata_size = cds;
123 
124  return 1;
125 }
126 
127 static uint64_t
128 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
129 {
130  struct ogg *ogg = ctx->priv_data;
131  struct ogg_stream *os = ogg->streams + idx;
132  struct theora_params *thp = os->private;
133  uint64_t iframe = gp >> thp->gpshift;
134  uint64_t pframe = gp & thp->gpmask;
135 
136  if (thp->version < 0x030201)
137  iframe++;
138 
139  if(!pframe)
140  os->pflags |= AV_PKT_FLAG_KEY;
141 
142  if (dts)
143  *dts = iframe + pframe;
144 
145  return iframe + pframe;
146 }
147 
148 const struct ogg_codec ff_theora_codec = {
149  .magic = "\200theora",
150  .magicsize = 7,
151  .header = theora_header,
152  .gptopts = theora_gptopts
153 };