ffmpeg / libavformat / oggdec.c @ 72415b2a
History | View | Annotate | Download (15.3 KB)
1 | 9146ca37 | Måns Rullgård | /*
|
---|---|---|---|
2 | * Ogg bitstream support
|
||
3 | * Luca Barbato <lu_zero@gentoo.org>
|
||
4 | * Based on tcvp implementation
|
||
5 | 115329f1 | Diego Biurrun | *
|
6 | 9146ca37 | Måns Rullgård | */
|
7 | |||
8 | /**
|
||
9 | Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
|
||
10 | |||
11 | Permission is hereby granted, free of charge, to any person
|
||
12 | obtaining a copy of this software and associated documentation
|
||
13 | files (the "Software"), to deal in the Software without
|
||
14 | restriction, including without limitation the rights to use, copy,
|
||
15 | modify, merge, publish, distribute, sublicense, and/or sell copies
|
||
16 | of the Software, and to permit persons to whom the Software is
|
||
17 | furnished to do so, subject to the following conditions:
|
||
18 | |||
19 | The above copyright notice and this permission notice shall be
|
||
20 | included in all copies or substantial portions of the Software.
|
||
21 | |||
22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||
26 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
27 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
29 | DEALINGS IN THE SOFTWARE.
|
||
30 | **/
|
||
31 | |||
32 | |||
33 | #include <stdio.h> |
||
34 | a0ddef24 | Diego Biurrun | #include "oggdec.h" |
35 | 9146ca37 | Måns Rullgård | #include "avformat.h" |
36 | 66061a12 | James Darnley | #include "vorbiscomment.h" |
37 | 9146ca37 | Måns Rullgård | |
38 | #define MAX_PAGE_SIZE 65307 |
||
39 | #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
|
||
40 | |||
41 | 77be08ee | Måns Rullgård | static const struct ogg_codec * const ogg_codecs[] = { |
42 | 32ad8692 | David Conrad | &ff_skeleton_codec, |
43 | 24ca518b | David Conrad | &ff_dirac_codec, |
44 | 547ea47d | Reimar Döffinger | &ff_speex_codec, |
45 | &ff_vorbis_codec, |
||
46 | &ff_theora_codec, |
||
47 | &ff_flac_codec, |
||
48 | 24ca518b | David Conrad | &ff_old_dirac_codec, |
49 | 547ea47d | Reimar Döffinger | &ff_old_flac_codec, |
50 | &ff_ogm_video_codec, |
||
51 | &ff_ogm_audio_codec, |
||
52 | &ff_ogm_text_codec, |
||
53 | &ff_ogm_old_codec, |
||
54 | 9146ca37 | Måns Rullgård | NULL
|
55 | }; |
||
56 | |||
57 | //FIXME We could avoid some structure duplication
|
||
58 | static int |
||
59 | ogg_save (AVFormatContext * s) |
||
60 | { |
||
61 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
62 | struct ogg_state *ost =
|
||
63 | ad3aa874 | Måns Rullgård | av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams)); |
64 | 9146ca37 | Måns Rullgård | int i;
|
65 | 899681cd | Björn Axelsson | ost->pos = url_ftell (s->pb); |
66 | 9146ca37 | Måns Rullgård | ost->curidx = ogg->curidx; |
67 | ost->next = ogg->state; |
||
68 | 20be72c8 | Måns Rullgård | ost->nstreams = ogg->nstreams; |
69 | 9146ca37 | Måns Rullgård | memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
|
70 | |||
71 | for (i = 0; i < ogg->nstreams; i++){ |
||
72 | 77be08ee | Måns Rullgård | struct ogg_stream *os = ogg->streams + i;
|
73 | 9146ca37 | Måns Rullgård | os->buf = av_malloc (os->bufsize); |
74 | memset (os->buf, 0, os->bufsize);
|
||
75 | memcpy (os->buf, ost->streams[i].buf, os->bufpos); |
||
76 | } |
||
77 | |||
78 | ogg->state = ost; |
||
79 | |||
80 | return 0; |
||
81 | } |
||
82 | |||
83 | static int |
||
84 | ogg_restore (AVFormatContext * s, int discard)
|
||
85 | { |
||
86 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
87 | 899681cd | Björn Axelsson | ByteIOContext *bc = s->pb; |
88 | 77be08ee | Måns Rullgård | struct ogg_state *ost = ogg->state;
|
89 | 9146ca37 | Måns Rullgård | int i;
|
90 | |||
91 | if (!ost)
|
||
92 | return 0; |
||
93 | |||
94 | ogg->state = ost->next; |
||
95 | |||
96 | if (!discard){
|
||
97 | for (i = 0; i < ogg->nstreams; i++) |
||
98 | av_free (ogg->streams[i].buf); |
||
99 | |||
100 | url_fseek (bc, ost->pos, SEEK_SET); |
||
101 | ogg->curidx = ost->curidx; |
||
102 | 20be72c8 | Måns Rullgård | ogg->nstreams = ost->nstreams; |
103 | memcpy(ogg->streams, ost->streams, |
||
104 | ost->nstreams * sizeof(*ogg->streams));
|
||
105 | 9146ca37 | Måns Rullgård | } |
106 | |||
107 | av_free (ost); |
||
108 | |||
109 | return 0; |
||
110 | } |
||
111 | |||
112 | static int |
||
113 | 77be08ee | Måns Rullgård | ogg_reset (struct ogg * ogg)
|
114 | 9146ca37 | Måns Rullgård | { |
115 | int i;
|
||
116 | |||
117 | for (i = 0; i < ogg->nstreams; i++){ |
||
118 | 77be08ee | Måns Rullgård | struct ogg_stream *os = ogg->streams + i;
|
119 | 9146ca37 | Måns Rullgård | os->bufpos = 0;
|
120 | os->pstart = 0;
|
||
121 | os->psize = 0;
|
||
122 | os->granule = -1;
|
||
123 | 5e15c7d9 | David Conrad | os->lastpts = AV_NOPTS_VALUE; |
124 | 2d4970d8 | David Conrad | os->lastdts = AV_NOPTS_VALUE; |
125 | 73823cb9 | David Conrad | os->sync_pos = -1;
|
126 | os->page_pos = 0;
|
||
127 | 9146ca37 | Måns Rullgård | os->nsegs = 0;
|
128 | os->segp = 0;
|
||
129 | ecc0027b | David Conrad | os->incomplete = 0;
|
130 | 9146ca37 | Måns Rullgård | } |
131 | |||
132 | ogg->curidx = -1;
|
||
133 | |||
134 | return 0; |
||
135 | } |
||
136 | |||
137 | 77be08ee | Måns Rullgård | static const struct ogg_codec * |
138 | 2d2f443d | Måns Rullgård | ogg_find_codec (uint8_t * buf, int size)
|
139 | 9146ca37 | Måns Rullgård | { |
140 | int i;
|
||
141 | |||
142 | for (i = 0; ogg_codecs[i]; i++) |
||
143 | if (size >= ogg_codecs[i]->magicsize &&
|
||
144 | !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize)) |
||
145 | return ogg_codecs[i];
|
||
146 | |||
147 | return NULL; |
||
148 | } |
||
149 | |||
150 | static int |
||
151 | ogg_new_stream (AVFormatContext * s, uint32_t serial) |
||
152 | { |
||
153 | |||
154 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
155 | 9146ca37 | Måns Rullgård | int idx = ogg->nstreams++;
|
156 | AVStream *st; |
||
157 | 77be08ee | Måns Rullgård | struct ogg_stream *os;
|
158 | 9146ca37 | Måns Rullgård | |
159 | ogg->streams = av_realloc (ogg->streams, |
||
160 | ogg->nstreams * sizeof (*ogg->streams));
|
||
161 | memset (ogg->streams + idx, 0, sizeof (*ogg->streams)); |
||
162 | os = ogg->streams + idx; |
||
163 | os->serial = serial; |
||
164 | os->bufsize = DECODER_BUFFER_SIZE; |
||
165 | 40c5e1fa | Måns Rullgård | os->buf = av_malloc(os->bufsize); |
166 | 9146ca37 | Måns Rullgård | os->header = -1;
|
167 | |||
168 | st = av_new_stream (s, idx); |
||
169 | if (!st)
|
||
170 | 769e10f0 | Panagiotis Issaris | return AVERROR(ENOMEM);
|
171 | 9146ca37 | Måns Rullgård | |
172 | av_set_pts_info(st, 64, 1, 1000000); |
||
173 | |||
174 | return idx;
|
||
175 | } |
||
176 | |||
177 | static int |
||
178 | 77be08ee | Måns Rullgård | ogg_new_buf(struct ogg *ogg, int idx) |
179 | 12a195e3 | Måns Rullgård | { |
180 | 77be08ee | Måns Rullgård | struct ogg_stream *os = ogg->streams + idx;
|
181 | ea02862a | Måns Rullgård | uint8_t *nb = av_malloc(os->bufsize); |
182 | 12a195e3 | Måns Rullgård | int size = os->bufpos - os->pstart;
|
183 | if(os->buf){
|
||
184 | memcpy(nb, os->buf + os->pstart, size); |
||
185 | av_free(os->buf); |
||
186 | } |
||
187 | os->buf = nb; |
||
188 | os->bufpos = size; |
||
189 | os->pstart = 0;
|
||
190 | |||
191 | return 0; |
||
192 | } |
||
193 | |||
194 | static int |
||
195 | 9146ca37 | Måns Rullgård | ogg_read_page (AVFormatContext * s, int *str)
|
196 | { |
||
197 | 899681cd | Björn Axelsson | ByteIOContext *bc = s->pb; |
198 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
199 | struct ogg_stream *os;
|
||
200 | 9146ca37 | Måns Rullgård | int i = 0; |
201 | int flags, nsegs;
|
||
202 | uint64_t gp; |
||
203 | uint32_t serial; |
||
204 | uint32_t seq; |
||
205 | uint32_t crc; |
||
206 | int size, idx;
|
||
207 | 191e8ca7 | Måns Rullgård | uint8_t sync[4];
|
208 | 9146ca37 | Måns Rullgård | int sp = 0; |
209 | |||
210 | if (get_buffer (bc, sync, 4) < 4) |
||
211 | return -1; |
||
212 | |||
213 | do{
|
||
214 | int c;
|
||
215 | |||
216 | if (sync[sp & 3] == 'O' && |
||
217 | sync[(sp + 1) & 3] == 'g' && |
||
218 | sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S') |
||
219 | break;
|
||
220 | |||
221 | c = url_fgetc (bc); |
||
222 | if (c < 0) |
||
223 | return -1; |
||
224 | sync[sp++ & 3] = c;
|
||
225 | }while (i++ < MAX_PAGE_SIZE);
|
||
226 | |||
227 | if (i >= MAX_PAGE_SIZE){
|
||
228 | av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
|
||
229 | return -1; |
||
230 | } |
||
231 | |||
232 | if (url_fgetc (bc) != 0) /* version */ |
||
233 | return -1; |
||
234 | |||
235 | flags = url_fgetc (bc); |
||
236 | gp = get_le64 (bc); |
||
237 | serial = get_le32 (bc); |
||
238 | seq = get_le32 (bc); |
||
239 | crc = get_le32 (bc); |
||
240 | nsegs = url_fgetc (bc); |
||
241 | |||
242 | idx = ogg_find_stream (ogg, serial); |
||
243 | if (idx < 0){ |
||
244 | idx = ogg_new_stream (s, serial); |
||
245 | if (idx < 0) |
||
246 | return -1; |
||
247 | } |
||
248 | |||
249 | os = ogg->streams + idx; |
||
250 | 73823cb9 | David Conrad | os->page_pos = url_ftell(bc) - 27;
|
251 | 9146ca37 | Måns Rullgård | |
252 | 40c5e1fa | Måns Rullgård | if(os->psize > 0) |
253 | 12a195e3 | Måns Rullgård | ogg_new_buf(ogg, idx); |
254 | |||
255 | 9146ca37 | Måns Rullgård | if (get_buffer (bc, os->segments, nsegs) < nsegs)
|
256 | return -1; |
||
257 | |||
258 | os->nsegs = nsegs; |
||
259 | os->segp = 0;
|
||
260 | |||
261 | size = 0;
|
||
262 | for (i = 0; i < nsegs; i++) |
||
263 | size += os->segments[i]; |
||
264 | |||
265 | ecc0027b | David Conrad | if (flags & OGG_FLAG_CONT || os->incomplete){
|
266 | 9146ca37 | Måns Rullgård | if (!os->psize){
|
267 | while (os->segp < os->nsegs){
|
||
268 | int seg = os->segments[os->segp++];
|
||
269 | os->pstart += seg; |
||
270 | if (seg < 255) |
||
271 | bad4a6bb | Peter Ross | break;
|
272 | 9146ca37 | Måns Rullgård | } |
273 | 73823cb9 | David Conrad | os->sync_pos = os->page_pos; |
274 | 9146ca37 | Måns Rullgård | } |
275 | }else{
|
||
276 | bad4a6bb | Peter Ross | os->psize = 0;
|
277 | 73823cb9 | David Conrad | os->sync_pos = os->page_pos; |
278 | 9146ca37 | Måns Rullgård | } |
279 | |||
280 | if (os->bufsize - os->bufpos < size){
|
||
281 | 2d2f443d | Måns Rullgård | uint8_t *nb = av_malloc (os->bufsize *= 2);
|
282 | 9146ca37 | Måns Rullgård | memcpy (nb, os->buf, os->bufpos); |
283 | av_free (os->buf); |
||
284 | os->buf = nb; |
||
285 | } |
||
286 | |||
287 | if (get_buffer (bc, os->buf + os->bufpos, size) < size)
|
||
288 | return -1; |
||
289 | |||
290 | os->bufpos += size; |
||
291 | os->granule = gp; |
||
292 | os->flags = flags; |
||
293 | |||
294 | if (str)
|
||
295 | *str = idx; |
||
296 | |||
297 | return 0; |
||
298 | } |
||
299 | |||
300 | static int |
||
301 | 73823cb9 | David Conrad | ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos) |
302 | 9146ca37 | Måns Rullgård | { |
303 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
304 | 5e15c7d9 | David Conrad | int idx, i;
|
305 | 77be08ee | Måns Rullgård | struct ogg_stream *os;
|
306 | 9146ca37 | Måns Rullgård | int complete = 0; |
307 | int segp = 0, psize = 0; |
||
308 | |||
309 | #if 0
|
||
310 | av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
|
||
311 | #endif
|
||
312 | |||
313 | do{
|
||
314 | idx = ogg->curidx; |
||
315 | |||
316 | while (idx < 0){ |
||
317 | if (ogg_read_page (s, &idx) < 0) |
||
318 | return -1; |
||
319 | } |
||
320 | |||
321 | os = ogg->streams + idx; |
||
322 | |||
323 | #if 0
|
||
324 | av_log (s, AV_LOG_DEBUG,
|
||
325 | "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
|
||
326 | idx, os->pstart, os->psize, os->segp, os->nsegs);
|
||
327 | #endif
|
||
328 | |||
329 | if (!os->codec){
|
||
330 | if (os->header < 0){ |
||
331 | os->codec = ogg_find_codec (os->buf, os->bufpos); |
||
332 | if (!os->codec){
|
||
333 | os->header = 0;
|
||
334 | return 0; |
||
335 | } |
||
336 | }else{
|
||
337 | return 0; |
||
338 | } |
||
339 | } |
||
340 | |||
341 | segp = os->segp; |
||
342 | psize = os->psize; |
||
343 | |||
344 | while (os->segp < os->nsegs){
|
||
345 | int ss = os->segments[os->segp++];
|
||
346 | os->psize += ss; |
||
347 | if (ss < 255){ |
||
348 | complete = 1;
|
||
349 | break;
|
||
350 | } |
||
351 | } |
||
352 | |||
353 | if (!complete && os->segp == os->nsegs){
|
||
354 | ogg->curidx = -1;
|
||
355 | ecc0027b | David Conrad | os->incomplete = 1;
|
356 | 9146ca37 | Måns Rullgård | } |
357 | }while (!complete);
|
||
358 | |||
359 | #if 0
|
||
360 | av_log (s, AV_LOG_DEBUG,
|
||
361 | "ogg_packet: idx %i, frame size %i, start %i\n",
|
||
362 | idx, os->psize, os->pstart);
|
||
363 | #endif
|
||
364 | |||
365 | ogg->curidx = idx; |
||
366 | ecc0027b | David Conrad | os->incomplete = 0;
|
367 | 9146ca37 | Måns Rullgård | |
368 | 81b743eb | David Conrad | if (os->header) {
|
369 | os->header = os->codec->header (s, idx); |
||
370 | if (!os->header){
|
||
371 | bad4a6bb | Peter Ross | os->segp = segp; |
372 | os->psize = psize; |
||
373 | 81b743eb | David Conrad | if (!ogg->headers)
|
374 | s->data_offset = os->sync_pos; |
||
375 | bad4a6bb | Peter Ross | ogg->headers = 1;
|
376 | 9146ca37 | Måns Rullgård | }else{
|
377 | bad4a6bb | Peter Ross | os->pstart += os->psize; |
378 | os->psize = 0;
|
||
379 | 9146ca37 | Måns Rullgård | } |
380 | 81b743eb | David Conrad | } else {
|
381 | e1a794b2 | Måns Rullgård | os->pflags = 0;
|
382 | 15299b38 | Justin Ruggles | os->pduration = 0;
|
383 | 9146ca37 | Måns Rullgård | if (os->codec && os->codec->packet)
|
384 | os->codec->packet (s, idx); |
||
385 | if (str)
|
||
386 | *str = idx; |
||
387 | 12a195e3 | Måns Rullgård | if (dstart)
|
388 | *dstart = os->pstart; |
||
389 | if (dsize)
|
||
390 | *dsize = os->psize; |
||
391 | 73823cb9 | David Conrad | if (fpos)
|
392 | *fpos = os->sync_pos; |
||
393 | 12a195e3 | Måns Rullgård | os->pstart += os->psize; |
394 | os->psize = 0;
|
||
395 | 73823cb9 | David Conrad | os->sync_pos = os->page_pos; |
396 | 9146ca37 | Måns Rullgård | } |
397 | |||
398 | 5e15c7d9 | David Conrad | // determine whether there are more complete packets in this page
|
399 | // if not, the page's granule will apply to this packet
|
||
400 | os->page_end = 1;
|
||
401 | for (i = os->segp; i < os->nsegs; i++)
|
||
402 | if (os->segments[i] < 255) { |
||
403 | os->page_end = 0;
|
||
404 | break;
|
||
405 | } |
||
406 | |||
407 | 9146ca37 | Måns Rullgård | if (os->segp == os->nsegs)
|
408 | ogg->curidx = -1;
|
||
409 | |||
410 | return 0; |
||
411 | } |
||
412 | |||
413 | static int |
||
414 | ogg_get_headers (AVFormatContext * s) |
||
415 | { |
||
416 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
417 | 9146ca37 | Måns Rullgård | |
418 | do{
|
||
419 | 73823cb9 | David Conrad | if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0) |
420 | 9146ca37 | Måns Rullgård | return -1; |
421 | }while (!ogg->headers);
|
||
422 | |||
423 | #if 0
|
||
424 | av_log (s, AV_LOG_DEBUG, "found headers\n");
|
||
425 | #endif
|
||
426 | |||
427 | return 0; |
||
428 | } |
||
429 | |||
430 | static int |
||
431 | ogg_get_length (AVFormatContext * s) |
||
432 | { |
||
433 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
434 | 9146ca37 | Måns Rullgård | int idx = -1, i; |
435 | bc5c918e | Diego Biurrun | int64_t size, end; |
436 | 69599eea | Måns Rullgård | |
437 | ceeacce6 | Aurelien Jacobs | if(url_is_streamed(s->pb))
|
438 | 69599eea | Måns Rullgård | return 0; |
439 | 9146ca37 | Måns Rullgård | |
440 | // already set
|
||
441 | if (s->duration != AV_NOPTS_VALUE)
|
||
442 | return 0; |
||
443 | |||
444 | 899681cd | Björn Axelsson | size = url_fsize(s->pb); |
445 | 56466d7b | Måns Rullgård | if(size < 0) |
446 | return 0; |
||
447 | ddd94932 | David Conrad | end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
|
448 | 56466d7b | Måns Rullgård | |
449 | 9146ca37 | Måns Rullgård | ogg_save (s); |
450 | 899681cd | Björn Axelsson | url_fseek (s->pb, end, SEEK_SET); |
451 | 9146ca37 | Måns Rullgård | |
452 | while (!ogg_read_page (s, &i)){
|
||
453 | e22f2aaf | Måns Rullgård | if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && |
454 | ogg->streams[i].codec) |
||
455 | 9146ca37 | Måns Rullgård | idx = i; |
456 | } |
||
457 | |||
458 | if (idx != -1){ |
||
459 | s->streams[idx]->duration = |
||
460 | 2d4970d8 | David Conrad | ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
|
461 | 77560b0e | David Conrad | if (s->streams[idx]->start_time != AV_NOPTS_VALUE)
|
462 | s->streams[idx]->duration -= s->streams[idx]->start_time; |
||
463 | 9146ca37 | Måns Rullgård | } |
464 | |||
465 | 56466d7b | Måns Rullgård | ogg->size = size; |
466 | 9146ca37 | Måns Rullgård | ogg_restore (s, 0);
|
467 | |||
468 | return 0; |
||
469 | } |
||
470 | |||
471 | |||
472 | static int |
||
473 | ogg_read_header (AVFormatContext * s, AVFormatParameters * ap) |
||
474 | { |
||
475 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
476 | c9da676d | Reimar Döffinger | int i;
|
477 | 9146ca37 | Måns Rullgård | ogg->curidx = -1;
|
478 | //linear headers seek from start
|
||
479 | if (ogg_get_headers (s) < 0){ |
||
480 | bad4a6bb | Peter Ross | return -1; |
481 | 9146ca37 | Måns Rullgård | } |
482 | |||
483 | c9da676d | Reimar Döffinger | for (i = 0; i < ogg->nstreams; i++) |
484 | if (ogg->streams[i].header < 0) |
||
485 | ogg->streams[i].codec = NULL;
|
||
486 | |||
487 | 9146ca37 | Måns Rullgård | //linear granulepos seek from end
|
488 | ogg_get_length (s); |
||
489 | |||
490 | //fill the extradata in the per codec callbacks
|
||
491 | return 0; |
||
492 | } |
||
493 | |||
494 | 6abaa272 | David Conrad | static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts) |
495 | { |
||
496 | struct ogg *ogg = s->priv_data;
|
||
497 | struct ogg_stream *os = ogg->streams + idx;
|
||
498 | int64_t pts = AV_NOPTS_VALUE; |
||
499 | |||
500 | if (dts)
|
||
501 | *dts = AV_NOPTS_VALUE; |
||
502 | |||
503 | if (os->lastpts != AV_NOPTS_VALUE) {
|
||
504 | pts = os->lastpts; |
||
505 | os->lastpts = AV_NOPTS_VALUE; |
||
506 | } |
||
507 | if (os->lastdts != AV_NOPTS_VALUE) {
|
||
508 | if (dts)
|
||
509 | *dts = os->lastdts; |
||
510 | os->lastdts = AV_NOPTS_VALUE; |
||
511 | } |
||
512 | if (os->page_end) {
|
||
513 | if (os->granule != -1LL) { |
||
514 | if (os->codec && os->codec->granule_is_start)
|
||
515 | pts = ogg_gptopts(s, idx, os->granule, dts); |
||
516 | else
|
||
517 | os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts); |
||
518 | os->granule = -1LL;
|
||
519 | } else
|
||
520 | av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
|
||
521 | } |
||
522 | return pts;
|
||
523 | } |
||
524 | 9146ca37 | Måns Rullgård | |
525 | static int |
||
526 | ogg_read_packet (AVFormatContext * s, AVPacket * pkt) |
||
527 | { |
||
528 | 77be08ee | Måns Rullgård | struct ogg *ogg;
|
529 | struct ogg_stream *os;
|
||
530 | 9146ca37 | Måns Rullgård | int idx = -1; |
531 | 12a195e3 | Måns Rullgård | int pstart, psize;
|
532 | d8b91fae | David Conrad | int64_t fpos, pts, dts; |
533 | 9146ca37 | Måns Rullgård | |
534 | 115329f1 | Diego Biurrun | //Get an ogg packet
|
535 | d8b91fae | David Conrad | retry:
|
536 | 9146ca37 | Måns Rullgård | do{
|
537 | 73823cb9 | David Conrad | if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0) |
538 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
539 | 9146ca37 | Måns Rullgård | }while (idx < 0 || !s->streams[idx]); |
540 | |||
541 | ogg = s->priv_data; |
||
542 | os = ogg->streams + idx; |
||
543 | |||
544 | d8b91fae | David Conrad | // pflags might not be set until after this
|
545 | pts = ogg_calc_pts(s, idx, &dts); |
||
546 | |||
547 | if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
|
||
548 | goto retry;
|
||
549 | os->keyframe_seek = 0;
|
||
550 | |||
551 | 9146ca37 | Måns Rullgård | //Alloc a pkt
|
552 | 12a195e3 | Måns Rullgård | if (av_new_packet (pkt, psize) < 0) |
553 | 6f3e0b21 | Panagiotis Issaris | return AVERROR(EIO);
|
554 | 9146ca37 | Måns Rullgård | pkt->stream_index = idx; |
555 | 12a195e3 | Måns Rullgård | memcpy (pkt->data, os->buf + pstart, psize); |
556 | 5e15c7d9 | David Conrad | |
557 | d8b91fae | David Conrad | pkt->pts = pts; |
558 | pkt->dts = dts; |
||
559 | e1a794b2 | Måns Rullgård | pkt->flags = os->pflags; |
560 | 15299b38 | Justin Ruggles | pkt->duration = os->pduration; |
561 | 73823cb9 | David Conrad | pkt->pos = fpos; |
562 | e1a794b2 | Måns Rullgård | |
563 | 12a195e3 | Måns Rullgård | return psize;
|
564 | 9146ca37 | Måns Rullgård | } |
565 | |||
566 | |||
567 | static int |
||
568 | ogg_read_close (AVFormatContext * s) |
||
569 | { |
||
570 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
571 | 9146ca37 | Måns Rullgård | int i;
|
572 | |||
573 | for (i = 0; i < ogg->nstreams; i++){ |
||
574 | av_free (ogg->streams[i].buf); |
||
575 | 1ed923ea | Måns Rullgård | av_free (ogg->streams[i].private); |
576 | 9146ca37 | Måns Rullgård | } |
577 | av_free (ogg->streams); |
||
578 | return 0; |
||
579 | } |
||
580 | |||
581 | |||
582 | static int64_t
|
||
583 | ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
|
||
584 | int64_t pos_limit) |
||
585 | { |
||
586 | 77be08ee | Måns Rullgård | struct ogg *ogg = s->priv_data;
|
587 | d8b91fae | David Conrad | struct ogg_stream *os = ogg->streams + stream_index;
|
588 | 899681cd | Björn Axelsson | ByteIOContext *bc = s->pb; |
589 | a1f29b95 | Reimar Döffinger | int64_t pts = AV_NOPTS_VALUE; |
590 | int i;
|
||
591 | url_fseek(bc, *pos_arg, SEEK_SET); |
||
592 | 873d117e | David Conrad | ogg_reset(ogg); |
593 | |||
594 | while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) { |
||
595 | if (i == stream_index) {
|
||
596 | pts = ogg_calc_pts(s, i, NULL);
|
||
597 | d8b91fae | David Conrad | if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
|
598 | pts = AV_NOPTS_VALUE; |
||
599 | a1f29b95 | Reimar Döffinger | } |
600 | 873d117e | David Conrad | if (pts != AV_NOPTS_VALUE)
|
601 | break;
|
||
602 | a1f29b95 | Reimar Döffinger | } |
603 | ogg_reset(ogg); |
||
604 | return pts;
|
||
605 | 9146ca37 | Måns Rullgård | } |
606 | |||
607 | d8b91fae | David Conrad | static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) |
608 | { |
||
609 | struct ogg *ogg = s->priv_data;
|
||
610 | struct ogg_stream *os = ogg->streams + stream_index;
|
||
611 | int ret;
|
||
612 | |||
613 | // Try seeking to a keyframe first. If this fails (very possible),
|
||
614 | // av_seek_frame will fall back to ignoring keyframes
|
||
615 | 72415b2a | Stefano Sabatini | if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
|
616 | d8b91fae | David Conrad | && !(flags & AVSEEK_FLAG_ANY)) |
617 | os->keyframe_seek = 1;
|
||
618 | |||
619 | ret = av_seek_frame_binary(s, stream_index, timestamp, flags); |
||
620 | if (ret < 0) |
||
621 | os->keyframe_seek = 0;
|
||
622 | return ret;
|
||
623 | } |
||
624 | |||
625 | 2e70e4aa | Måns Rullgård | static int ogg_probe(AVProbeData *p) |
626 | { |
||
627 | if (p->buf[0] == 'O' && p->buf[1] == 'g' && |
||
628 | p->buf[2] == 'g' && p->buf[3] == 'S' && |
||
629 | p->buf[4] == 0x0 && p->buf[5] <= 0x7 ) |
||
630 | return AVPROBE_SCORE_MAX;
|
||
631 | else
|
||
632 | return 0; |
||
633 | } |
||
634 | |||
635 | ff70e601 | Måns Rullgård | AVInputFormat ogg_demuxer = { |
636 | 9146ca37 | Måns Rullgård | "ogg",
|
637 | bde15e74 | Stefano Sabatini | NULL_IF_CONFIG_SMALL("Ogg"),
|
638 | 77be08ee | Måns Rullgård | sizeof (struct ogg), |
639 | 2e70e4aa | Måns Rullgård | ogg_probe, |
640 | 9146ca37 | Måns Rullgård | ogg_read_header, |
641 | ogg_read_packet, |
||
642 | ogg_read_close, |
||
643 | d8b91fae | David Conrad | ogg_read_seek, |
644 | a1f29b95 | Reimar Döffinger | ogg_read_timestamp, |
645 | 9146ca37 | Måns Rullgård | .extensions = "ogg",
|
646 | d7bb185f | Justin Ruggles | .metadata_conv = ff_vorbiscomment_metadata_conv, |
647 | 9146ca37 | Måns Rullgård | }; |