FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
oggparsetheora.c
Go to the documentation of this file.
1 /**
2  Copyright (C) 2005 Matthieu CASTET, Alex Beregszaszi
3 
4  Permission is hereby granted, free of charge, to any person
5  obtaining a copy of this software and associated documentation
6  files (the "Software"), to deal in the Software without
7  restriction, including without limitation the rights to use, copy,
8  modify, merge, publish, distribute, sublicense, and/or sell copies
9  of the Software, and to permit persons to whom the Software is
10  furnished to do so, subject to the following conditions:
11 
12  The above copyright notice and this permission notice shall be
13  included in all copies or substantial portions of the Software.
14 
15  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23 **/
24 
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, 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  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  break;
115  case 0x81:
116  ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 7);
117  case 0x82:
118  if (!thp->version)
119  return -1;
120  break;
121  default:
122  av_log(s, AV_LOG_ERROR, "Unknown header type %X\n", os->buf[os->pstart]);
123  return -1;
124  }
125 
126  if ((err = av_reallocp(&st->codec->extradata,
127  cds + FF_INPUT_BUFFER_PADDING_SIZE)) < 0) {
128  st->codec->extradata_size = 0;
129  return err;
130  }
131  cdp = st->codec->extradata + st->codec->extradata_size;
132  *cdp++ = os->psize >> 8;
133  *cdp++ = os->psize & 0xff;
134  memcpy (cdp, os->buf + os->pstart, os->psize);
135  st->codec->extradata_size = cds;
136 
137  return 1;
138 }
139 
140 static uint64_t
141 theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, int64_t *dts)
142 {
143  struct ogg *ogg = ctx->priv_data;
144  struct ogg_stream *os = ogg->streams + idx;
145  struct theora_params *thp = os->private;
146  uint64_t iframe, pframe;
147 
148  if (!thp)
149  return AV_NOPTS_VALUE;
150 
151  iframe = gp >> thp->gpshift;
152  pframe = gp & thp->gpmask;
153 
154  if (thp->version < 0x030201)
155  iframe++;
156 
157  if(!pframe)
158  os->pflags |= AV_PKT_FLAG_KEY;
159 
160  if (dts)
161  *dts = iframe + pframe;
162 
163  return iframe + pframe;
164 }
165 
166 static int theora_packet(AVFormatContext *s, int idx)
167 {
168  struct ogg *ogg = s->priv_data;
169  struct ogg_stream *os = ogg->streams + idx;
170  int duration;
171 
172  /* first packet handling
173  here we parse the duration of each packet in the first page and compare
174  the total duration to the page granule to find the encoder delay and
175  set the first timestamp */
176 
177  if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
178  int seg;
179 
180  duration = 1;
181  for (seg = os->segp; seg < os->nsegs; seg++) {
182  if (os->segments[seg] < 255)
183  duration ++;
184  }
185 
186  os->lastpts = os->lastdts = theora_gptopts(s, idx, os->granule, NULL) - duration;
187  if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
188  s->streams[idx]->start_time = os->lastpts;
189  if (s->streams[idx]->duration)
190  s->streams[idx]->duration -= s->streams[idx]->start_time;
191  }
192  }
193 
194  /* parse packet duration */
195  if (os->psize > 0) {
196  os->pduration = 1;
197  }
198 
199  return 0;
200 }
201 
202 const struct ogg_codec ff_theora_codec = {
203  .magic = "\200theora",
204  .magicsize = 7,
205  .header = theora_header,
206  .packet = theora_packet,
207  .gptopts = theora_gptopts,
208  .nb_header = 3,
209 };