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