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  switch (os->buf[os->pstart]) {
57  case 0x80: {
58  GetBitContext gb;
59  int width, height;
60  AVRational timebase;
61 
62  init_get_bits(&gb, os->buf + os->pstart, os->psize*8);
63 
64  skip_bits_long(&gb, 7*8); /* 0x80"theora" */
65 
66  thp->version = get_bits_long(&gb, 24);
67  if (thp->version < 0x030100)
68  {
70  "Too old or unsupported Theora (%x)\n", thp->version);
71  return -1;
72  }
73 
74  width = get_bits(&gb, 16) << 4;
75  height = get_bits(&gb, 16) << 4;
76  avcodec_set_dimensions(st->codec, width, height);
77 
78  if (thp->version >= 0x030400)
79  skip_bits(&gb, 100);
80 
81  if (thp->version >= 0x030200) {
82  width = get_bits_long(&gb, 24);
83  height = get_bits_long(&gb, 24);
84  if ( width <= st->codec->width && width > st->codec->width-16
85  && height <= st->codec->height && height > st->codec->height-16)
86  avcodec_set_dimensions(st->codec, width, height);
87 
88  skip_bits(&gb, 16);
89  }
90  timebase.den = get_bits_long(&gb, 32);
91  timebase.num = get_bits_long(&gb, 32);
92  if (!(timebase.num > 0 && timebase.den > 0)) {
93  av_log(s, AV_LOG_WARNING, "Invalid time base in theora stream, assuming 25 FPS\n");
94  timebase.num = 1;
95  timebase.den = 25;
96  }
97  avpriv_set_pts_info(st, 64, timebase.num, timebase.den);
98 
99  st->sample_aspect_ratio.num = get_bits_long(&gb, 24);
100  st->sample_aspect_ratio.den = get_bits_long(&gb, 24);
101 
102  if (thp->version >= 0x030200)
103  skip_bits_long(&gb, 38);
104  if (thp->version >= 0x304000)
105  skip_bits(&gb, 2);
106 
107  thp->gpshift = get_bits(&gb, 5);
108  thp->gpmask = (1 << thp->gpshift) - 1;
109 
113 
114  }
115  break;
116  case 0x81:
117  ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
118  case 0x82:
119  if (!thp->version)
120  return -1;
121  break;
122  default:
123  return -1;
124  }
125 
128  cdp = st->codec->extradata + st->codec->extradata_size;
129  *cdp++ = os->psize >> 8;
130  *cdp++ = os->psize & 0xff;
131  memcpy (cdp, os->buf + os->pstart, os->psize);
132  st->codec->extradata_size = cds;
133 
134  return 1;
135 }
136 
137 static uint64_t
138 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
139 {
140  struct ogg *ogg = ctx->priv_data;
141  struct ogg_stream *os = ogg->streams + idx;
142  struct theora_params *thp = os->private;
143  uint64_t iframe, pframe;
144 
145  if (!thp)
146  return AV_NOPTS_VALUE;
147 
148  iframe = gp >> thp->gpshift;
149  pframe = gp & thp->gpmask;
150 
151  if (thp->version < 0x030201)
152  iframe++;
153 
154  if(!pframe)
155  os->pflags |= AV_PKT_FLAG_KEY;
156 
157  if (dts)
158  *dts = iframe + pframe;
159 
160  return iframe + pframe;
161 }
162 
163 const struct ogg_codec ff_theora_codec = {
164  .magic = "\200theora",
165  .magicsize = 7,
166  .header = theora_header,
167  .gptopts = theora_gptopts,
168  .nb_header = 3,
169 };