cleanup: Add const qualifiers for struct ad_functions pointers
[mplayer.git] / libmpdemux / demux_ogg.c
blob4234eb94986e165e94a410804856a3e5388b4673
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "config.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <math.h>
26 #include <inttypes.h>
28 #include "options.h"
29 #include "mp_msg.h"
30 #include "stream/stream.h"
31 #include "demuxer.h"
32 #include "stheader.h"
33 #include "ffmpeg_files/intreadwrite.h"
34 #include "aviprint.h"
35 #include "demux_mov.h"
36 #include "demux_ogg.h"
38 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
39 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
40 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
42 #ifdef CONFIG_TREMOR
43 #include <tremor/ogg.h>
44 #include <tremor/ivorbiscodec.h>
45 #else
46 #include <ogg/ogg.h>
47 #include <vorbis/codec.h>
48 #endif
50 #ifdef CONFIG_OGGTHEORA
51 #include <theora/theora.h>
52 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
53 #endif
55 #define BLOCK_SIZE 4096
57 /* Theora decoder context : we won't be able to interpret granule positions
58 * without using theora_granule_time with the theora_state of the stream.
59 * This is duplicated in `vd_theora.c'; put this in a common header?
61 #ifdef CONFIG_OGGTHEORA
62 typedef struct theora_struct_st {
63 theora_state st;
64 theora_comment cc;
65 theora_info inf;
66 } theora_struct_t;
67 #endif
69 //// OggDS headers
70 // Header for the new header format
71 typedef struct stream_header_video {
72 ogg_int32_t width;
73 ogg_int32_t height;
74 } stream_header_video;
76 typedef struct stream_header_audio {
77 ogg_int16_t channels;
78 ogg_int16_t blockalign;
79 ogg_int32_t avgbytespersec;
80 } stream_header_audio;
82 typedef struct __attribute__((__packed__)) stream_header {
83 char streamtype[8];
84 char subtype[4];
86 ogg_int32_t size; // size of the structure
88 ogg_int64_t time_unit; // in reference time
89 ogg_int64_t samples_per_unit;
90 ogg_int32_t default_len; // in media time
92 ogg_int32_t buffersize;
93 ogg_int16_t bits_per_sample;
95 ogg_int16_t padding;
97 union {
98 // Video specific
99 stream_header_video video;
100 // Audio specific
101 stream_header_audio audio;
102 } sh;
103 } stream_header;
105 /// Our private datas
107 typedef struct ogg_syncpoint {
108 int64_t granulepos;
109 off_t page_pos;
110 } ogg_syncpoint_t;
112 /// A logical stream
113 typedef struct ogg_stream {
114 /// Timestamping stuff
115 float samplerate; /// granulpos 2 time
116 int64_t lastpos;
117 int32_t lastsize;
118 int keyframe_frequency_force;
120 // Logical stream state
121 ogg_stream_state stream;
122 int hdr_packets;
123 int vorbis;
124 int speex;
125 int theora;
126 int flac;
127 int text;
128 int id;
130 vorbis_info vi;
131 int vi_initialized;
133 void *ogg_d;
134 } ogg_stream_t;
136 typedef struct ogg_demuxer {
137 /// Physical stream state
138 ogg_sync_state sync;
139 /// Current page
140 ogg_page page;
141 /// Logical streams
142 ogg_stream_t *subs;
143 int num_sub;
144 ogg_syncpoint_t *syncpoints;
145 int num_syncpoint;
146 off_t pos, last_size;
147 int64_t initial_granulepos;
148 int64_t final_granulepos;
149 int64_t duration;
151 /* Used for subtitle switching. */
152 int n_text;
153 int *text_ids;
154 char **text_langs;
155 } ogg_demuxer_t;
157 #define NUM_VORBIS_HDR_PACKETS 3
159 /// Some defines from OggDS
160 #define PACKET_TYPE_HEADER 0x01
161 #define PACKET_TYPE_BITS 0x07
162 #define PACKET_LEN_BITS01 0xc0
163 #define PACKET_LEN_BITS2 0x02
164 #define PACKET_IS_SYNCPOINT 0x08
166 //-------- subtitle support - should be moved to decoder layer, and queue
167 // - subtitles up in demuxer buffer...
169 #include "subreader.h"
170 #include "libvo/sub.h"
171 #define OGG_SUB_MAX_LINE 128
173 static subtitle ogg_sub;
174 //FILE* subout;
176 static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
178 int lcv;
179 char *packet = pack->packet;
181 if (pack->bytes < 4)
182 return;
183 mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
184 (unsigned char)packet[0],
185 (unsigned char)packet[1],
186 (unsigned char)packet[2],
187 &packet[3]);
189 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
190 // Find data start
191 double endpts = MP_NOPTS_VALUE;
192 int32_t duration = 0;
193 int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i;
195 hdrlen |= (*packet & PACKET_LEN_BITS2) << 1;
196 lcv = 1 + hdrlen;
197 if (pack->bytes < lcv)
198 return;
199 for (i = hdrlen; i > 0; i--) {
200 duration <<= 8;
201 duration |= (unsigned char)packet[i];
203 if (hdrlen > 0 && duration > 0) {
204 float pts;
206 if (pack->granulepos == -1)
207 pack->granulepos = os->lastpos + os->lastsize;
208 pts = (float)pack->granulepos / (float)os->samplerate;
209 endpts = 1.0 + pts + (float)duration / 1000.0;
211 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
212 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
215 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n",
216 ogg_sub.lines, ogg_sub.text[0]);
217 #ifdef CONFIG_ICONV
218 subcp_recode(&ogg_sub);
219 #endif
220 vo_sub = &ogg_sub;
221 vo_osd_changed(OSDTYPE_SUBTITLE);
225 // get the logical stream of the current page
226 // fill os if non NULL and return the stream id
227 static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d,
228 ogg_stream_state **os)
230 int id, s_no;
231 ogg_page *page = &ogg_d->page;
233 s_no = ogg_page_serialno(page);
235 for (id = 0; id < ogg_d->num_sub; id++)
236 if (s_no == ogg_d->subs[id].stream.serialno)
237 break;
239 if (id == ogg_d->num_sub) {
240 // If we have only one vorbis stream allow the stream id to change
241 // it's normal on radio stream (each song have an different id).
242 // But we (or the codec?) should check that the samplerate, etc
243 // doesn't change (for radio stream it's ok)
244 if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
245 ogg_stream_reset(&ogg_d->subs[0].stream);
246 ogg_stream_init(&ogg_d->subs[0].stream, s_no);
247 id = 0;
248 } else
249 return -1;
252 if (os)
253 *os = &ogg_d->subs[id].stream;
255 return id;
258 static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack,
259 float *pts, int *flags,
260 int samplesize)
262 unsigned char *data = pack->packet;
263 int size = pack->bytes;
265 *pts = MP_NOPTS_VALUE;
266 *flags = 0;
268 if (os->vorbis) {
269 if (*pack->packet & PACKET_TYPE_HEADER) {
270 os->hdr_packets++;
271 } else {
272 vorbis_info *vi;
273 int32_t blocksize = 0;
275 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
276 vi = os->vi_initialized ? &os->vi : NULL;
277 if (vi)
278 blocksize = vorbis_packet_blocksize(vi, pack) / samplesize;
279 // Calculate the timestamp if the packet don't have any
280 if (pack->granulepos == -1) {
281 pack->granulepos = os->lastpos;
282 if (os->lastsize > 0)
283 pack->granulepos += os->lastsize;
284 } else
285 *flags = 1;
286 if (vi)
287 *pts = pack->granulepos / (float)vi->rate;
288 os->lastsize = blocksize;
289 os->lastpos = pack->granulepos;
291 } else if (os->speex) {
292 // whole packet (default)
293 # ifdef CONFIG_OGGTHEORA
294 } else if (os->theora) {
295 /* we pass complete packets to theora, mustn't strip the header! */
296 os->lastsize = 1;
298 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
299 have theora_state st, until all header packets were passed to the
300 decoder. */
301 if (!size || !(*data&0x80)) {
302 int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1);
303 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
305 if (pack->granulepos >= 0) {
306 os->lastpos = pack->granulepos >> keyframe_granule_shift;
307 os->lastpos += pack->granulepos & iframemask;
308 *flags = (pack->granulepos & iframemask) == 0;
309 } else {
310 os->lastpos++;
312 pack->granulepos = os->lastpos;
313 *pts = (double)os->lastpos / (double)os->samplerate;
315 #endif /* CONFIG_OGGTHEORA */
316 } else if (os->flac) {
317 /* we pass complete packets to flac, mustn't strip the header! */
318 if (os->flac == 2 && pack->packet[0] != 0xff)
319 return NULL;
320 } else {
321 if (*pack->packet & PACKET_TYPE_HEADER) {
322 os->hdr_packets++;
323 } else {
324 // Find data start
325 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6;
327 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1;
328 data = pack->packet + 1 + hdrlen;
329 // Calculate the timestamp
330 if (pack->granulepos == -1)
331 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
332 // If we already have a timestamp it can be a syncpoint
333 if (*pack->packet & PACKET_IS_SYNCPOINT)
334 *flags = 1;
335 *pts = pack->granulepos / os->samplerate;
336 // Save the packet length and timestamp
337 os->lastsize = 0;
338 while (hdrlen) {
339 os->lastsize <<= 8;
340 os->lastsize |= pack->packet[hdrlen];
341 hdrlen--;
343 os->lastpos = pack->granulepos;
346 return data;
349 // check if clang has substring from comma separated langlist
350 static int demux_ogg_check_lang(const char *clang, const char *langlist)
352 const char *c;
354 if (!langlist || !*langlist)
355 return 0;
356 while ((c = strchr(langlist, ','))) {
357 if (!strncasecmp(clang, langlist, c - langlist))
358 return 1;
359 langlist = &c[1];
361 if (!strncasecmp(clang, langlist, strlen(langlist)))
362 return 1;
363 return 0;
366 /** \brief Change the current subtitle stream and return its ID.
368 \param demuxer The demuxer whose subtitle stream will be changed.
369 \param new_num The number of the new subtitle track. The number must be
370 between 0 and ogg_d->n_text - 1.
372 \returns The Ogg stream number ( = page serial number) of the newly selected
373 track.
375 static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
377 ogg_demuxer_t *ogg_d = demuxer->priv;
378 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
381 /** \brief Translate the ogg track number into the subtitle number.
382 * \param demuxer The demuxer about whose subtitles we are inquiring.
383 * \param id The ogg track number of the subtitle track.
385 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id)
387 ogg_demuxer_t *ogg_d = demuxer->priv;
388 int i;
390 for (i = 0; i < ogg_d->n_text; i++)
391 if (ogg_d->text_ids[i] == id)
392 return i;
393 return -1;
396 /// Try to print out comments and also check for LANGUAGE= tag
397 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os,
398 int id, vorbis_comment *vc)
400 const char *hdr, *val;
401 char **cmt = vc->user_comments;
402 int index, i;
403 ogg_demuxer_t *ogg_d = d->priv;
404 static const struct table {
405 const char *ogg;
406 const char *mp;
407 } table[] = {
408 { "ENCODED_USING", "Software" },
409 { "ENCODER_URL", "Encoder URL" },
410 { "TITLE", "Title" },
411 { "ARTIST", "Artist" },
412 { "COMMENT", "Comments" },
413 { "DATE", "Creation Date" },
414 { "GENRE", "Genre" },
415 { "ALBUM", "Album" },
416 { "TRACKNUMBER", "Track" },
417 { NULL, NULL },
420 while (*cmt) {
421 hdr = NULL;
422 if (!strncasecmp(*cmt, "LANGUAGE=", 9)) {
423 val = *cmt + 9;
424 if (ogg_d->subs[id].text)
425 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n",
426 ogg_d->subs[id].id, val);
427 else if (id != d->video->id)
428 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n",
429 ogg_d->subs[id].id, val);
430 if (ogg_d->subs[id].text)
431 mp_msg(MSGT_DEMUX, MSGL_INFO,
432 "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
433 ogg_d->subs[id].id, val);
434 // copy this language name into the array
435 index = demux_ogg_sub_reverse_id(d, id);
436 if (index >= 0) {
437 sh_sub_t *sh;
439 // in case of malicious files with more than one lang per track:
440 if (ogg_d->text_langs[index])
441 free(ogg_d->text_langs[index]);
442 ogg_d->text_langs[index] = strdup(val);
443 sh = d->s_streams[index];
444 if (sh && sh->lang)
445 free(sh->lang);
446 if (sh)
447 sh->lang = strdup(val);
449 // check for -slang if subs are uninitialized yet
450 if (os->text && d->sub->id < 0
451 && demux_ogg_check_lang(val, d->opts->sub_lang)) {
452 d->sub->id = index;
453 d->opts->sub_id = index;
454 mp_msg(MSGT_DEMUX, MSGL_V,
455 "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
456 id, val);
458 else
459 hdr = "Language";
461 else {
462 for (i = 0; table[i].ogg; i++) {
463 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
464 (*cmt)[strlen(table[i].ogg)] == '=') {
465 hdr = table[i].mp;
466 val = *cmt + strlen(table[i].ogg) + 1;
470 if (hdr)
471 demux_info_add(d, hdr, val);
472 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
473 cmt++;
477 /// Calculate the timestamp and add the packet to the demux stream
478 // return 1 if the packet was added, 0 otherwise
479 static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
480 int id, ogg_packet *pack)
482 demuxer_t *d = ds->demuxer;
483 demux_packet_t *dp;
484 unsigned char *data;
485 float pts = 0;
486 int flags = 0;
487 int samplesize = 1;
489 // If packet is an comment header then we try to get comments at first
490 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
491 vorbis_info vi;
492 vorbis_comment vc;
494 vorbis_info_init(&vi);
495 vorbis_comment_init(&vc);
496 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
497 if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
498 demux_ogg_check_comments(d, os, id, &vc);
499 vorbis_comment_clear(&vc);
500 vorbis_info_clear(&vi);
502 if (os->text) {
503 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
504 demux_ogg_add_sub(os, pack);
505 return 0;
507 if (os->speex) {
508 // discard first two packets, they contain the header and comment
509 if (os->hdr_packets < 2) {
510 os->hdr_packets++;
511 return 0;
513 } else {
514 // If packet is an header we jump it except for vorbis and theora
515 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
516 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
517 // handled differently for each and every stream type. The joy! The joy!
518 if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
519 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
520 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
521 return 0;
524 // For vorbis packet the packet is the data, for other codec we must jump
525 // the header
526 if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
527 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
529 data = demux_ogg_read_packet(os, pack, &pts, &flags, samplesize);
530 if (!data)
531 return 0;
533 /// Clear subtitles if necessary (for broken files)
534 if (sub_clear_text(&ogg_sub, pts)) {
535 vo_sub = &ogg_sub;
536 vo_osd_changed(OSDTYPE_SUBTITLE);
538 /// Send the packet
539 dp = new_demux_packet(pack->bytes - (data - pack->packet));
540 memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
541 dp->pts = pts;
542 dp->flags = flags;
543 ds_add_packet(ds, dp);
544 mp_msg(MSGT_DEMUX, MSGL_DBG2,
545 "New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
546 dp, ds, pts, dp->len, flags);
547 return 1;
550 /// if -forceidx build a table of all syncpoints to make seeking easier
551 /// otherwise try to get at least the final_granulepos
552 static void demux_ogg_scan_stream(demuxer_t *demuxer)
554 ogg_demuxer_t *ogg_d = demuxer->priv;
555 stream_t *s = demuxer->stream;
556 ogg_sync_state *sync = &ogg_d->sync;
557 ogg_page *page = &ogg_d->page;
558 ogg_stream_state *oss;
559 ogg_stream_t *os;
560 ogg_packet op;
561 int np, sid, p, samplesize = 1;
562 off_t pos, last_pos;
564 pos = last_pos = demuxer->movi_start;
566 // Reset the stream
567 stream_seek(s, demuxer->movi_start);
568 ogg_sync_reset(sync);
570 // Get the serial number of the stream we use
571 if (demuxer->video->id >= 0) {
572 sid = demuxer->video->id;
573 } else if (demuxer->audio->id >= 0) {
574 sid = demuxer->audio->id;
575 if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
576 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
577 } else
578 return;
579 os = &ogg_d->subs[sid];
580 oss = &os->stream;
582 while (1) {
583 np = ogg_sync_pageseek(sync, page);
584 if (np < 0) { // We had to skip some bytes
585 if (index_mode == 2)
586 mp_msg(MSGT_DEMUX, MSGL_ERR,
587 "Bad page sync while building syncpoints table (%d)\n",
588 -np);
589 pos += -np;
590 continue;
592 if (np <= 0) { // We need more data
593 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
594 int len = stream_read(s, buf, BLOCK_SIZE);
596 if (len == 0 && s->eof)
597 break;
598 ogg_sync_wrote(sync, len);
599 continue;
601 // The page is ready
602 //ogg_sync_pageout(sync, page);
603 if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
604 pos += np;
605 continue;
607 if (ogg_stream_pagein(oss, page) != 0) {
608 mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
609 pos += np;
610 continue;
612 p = 0;
613 while (ogg_stream_packetout(oss, &op) == 1) {
614 float pts;
615 int flags;
617 demux_ogg_read_packet(os, &op, &pts, &flags, samplesize);
618 if (op.granulepos >= 0) {
619 ogg_d->final_granulepos = op.granulepos;
620 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
621 ogg_d->initial_granulepos = op.granulepos;
622 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
623 //the 270000 are just a wild guess
624 stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
625 ogg_sync_reset(sync);
626 continue;
630 if (index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
631 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1)
632 break;
633 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t));
634 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
635 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
636 ogg_d->num_syncpoint++;
638 p++;
640 if (p > 1 || (p == 1 && !ogg_page_continued(page)))
641 last_pos = pos;
642 pos += np;
643 if (index_mode == 2)
644 mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r",
645 (int)(pos * 100 / s->end_pos));
648 if (index_mode == 2) {
649 mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
650 mp_msg(MSGT_DEMUX, MSGL_V,
651 "Ogg syncpoints table builed: %d syncpoints\n",
652 ogg_d->num_syncpoint);
655 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n",
656 ogg_d->final_granulepos);
658 stream_reset(s);
659 stream_seek(s, demuxer->movi_start);
660 ogg_sync_reset(sync);
661 for (np = 0; np < ogg_d->num_sub; np++) {
662 ogg_stream_reset(&ogg_d->subs[np].stream);
663 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
666 // Get the first page
667 while (1) {
668 np = ogg_sync_pageout(sync, page);
669 if (np <= 0) { // We need more data
670 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
671 int len = stream_read(s, buf, BLOCK_SIZE);
673 if (len == 0 && s->eof) {
674 mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n");
675 break;
677 ogg_sync_wrote(sync, len);
678 continue;
680 demux_ogg_get_page_stream(ogg_d, &oss);
681 ogg_stream_pagein(oss, page);
682 break;
686 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
688 int i, offset;
689 int ris, init_error = 0;
690 ogg_packet op[3];
691 unsigned char *buf[3];
692 unsigned char *ptr;
693 unsigned int len;
694 ogg_stream_t *os = &od->subs[sh->ds->id];
695 vorbis_comment vc;
697 vorbis_info_init(&os->vi);
698 vorbis_comment_init(&vc);
699 for (i = 0; i < 3; i++) {
700 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
701 mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
702 if (op[i].bytes < 0) {
703 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
704 return;
706 buf[i] = malloc(op[i].bytes);
707 if (!buf[i])
708 return;
709 memcpy(buf[i], op[i].packet, op[i].bytes);
711 op[i].b_o_s = (i == 0);
712 ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]);
713 if (ris < 0) {
714 init_error = 1;
715 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
718 vorbis_comment_clear(&vc);
719 if (!init_error)
720 os->vi_initialized = 1;
722 len = op[0].bytes + op[1].bytes + op[2].bytes;
723 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len / 255 + 64);
724 ptr = (unsigned char*)(sh->wf + 1);
726 ptr[0] = 2;
727 offset = 1;
728 offset += store_ughvlc(&ptr[offset], op[0].bytes);
729 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset);
730 offset += store_ughvlc(&ptr[offset], op[1].bytes);
731 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset);
732 for (i = 0; i < 3; i++) {
733 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
734 memcpy(&ptr[offset], buf[i], op[i].bytes);
735 offset += op[i].bytes;
737 sh->wf->cbSize = offset;
738 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
739 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
741 if (op[0].bytes >= 29) {
742 unsigned int br;
743 int nombr, minbr, maxbr;
745 ptr = buf[0];
746 sh->channels = ptr[11];
747 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
748 maxbr = AV_RL32(&ptr[16]); //max
749 nombr = AV_RL32(&ptr[20]); //nominal
750 minbr = AV_RL32(&ptr[24]); //minimum
752 if (maxbr == -1)
753 maxbr = 0;
754 if (nombr == -1)
755 nombr = 0;
756 if (minbr == -1)
757 minbr = 0;
759 br = maxbr / 8;
760 if (!br)
761 br = nombr / 8;
762 if (!br)
763 br = minbr / 8;
764 sh->wf->nAvgBytesPerSec = br;
765 sh->wf->wBitsPerSample = 16;
766 sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8;
768 mp_msg(MSGT_DEMUX, MSGL_V,
769 "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
770 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec,
771 maxbr, nombr, minbr);
773 free(buf[2]);
774 free(buf[1]);
775 free(buf[0]);
778 /// Open an ogg physical stream
779 // Not static because it's used also in demuxer_avi.c
780 int demux_ogg_open(demuxer_t *demuxer)
782 ogg_demuxer_t *ogg_d;
783 stream_t *s;
784 char *buf;
785 int np, s_no, n_audio = 0, n_video = 0;
786 int audio_id = -1, video_id = -1, text_id = -1;
787 ogg_sync_state *sync;
788 ogg_page *page;
789 ogg_packet pack;
790 sh_audio_t *sh_a;
791 sh_video_t *sh_v;
793 #ifdef CONFIG_ICONV
794 subcp_open(NULL);
795 #endif
797 s = demuxer->stream;
799 demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d));
800 sync = &ogg_d->sync;
801 page = &ogg_d->page;
803 ogg_sync_init(sync);
805 while (1) {
806 /// Try to get a page
807 ogg_d->pos += ogg_d->last_size;
808 np = ogg_sync_pageseek(sync, page);
809 /// Error
810 if (np < 0) {
811 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n");
812 goto err_out;
814 /// Need some more data
815 if (np == 0) {
816 int len;
818 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
819 len = stream_read(s, buf, BLOCK_SIZE);
820 if (len == 0 && s->eof) {
821 goto err_out;
823 ogg_sync_wrote(sync, len);
824 continue;
826 ogg_d->last_size = np;
827 // We got one page now
829 if (!ogg_page_bos(page)) { // It's not a beginning page
830 // Header parsing end here, we need to get the page otherwise it will be lost
831 int id = demux_ogg_get_page_stream(ogg_d, NULL);
832 if (id >= 0)
833 ogg_stream_pagein(&ogg_d->subs[id].stream, page);
834 else
835 mp_msg(MSGT_DEMUX, MSGL_ERR,
836 "Ogg : Warning found none bos page from unknown stream %d\n",
837 ogg_page_serialno(page));
838 break;
841 /// Init the data structure needed for a logical stream
842 ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1,
843 sizeof(ogg_stream_t));
844 memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t));
845 /// Get the stream serial number
846 s_no = ogg_page_serialno(page);
847 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no);
848 mp_msg(MSGT_DEMUX, MSGL_DBG2,
849 "Ogg : Found a stream with serial=%d\n", s_no);
850 // Take the first page
851 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page);
852 // Get first packet of the page
853 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack);
855 // Reset our vars
856 sh_a = NULL;
857 sh_v = NULL;
859 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
861 // Check for Vorbis
862 if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) {
863 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
864 sh_a->format = FOURCC_VORBIS;
865 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
866 ogg_d->subs[ogg_d->num_sub].id = n_audio;
867 n_audio++;
868 mp_msg(MSGT_DEMUX, MSGL_INFO,
869 "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
870 ogg_d->num_sub, n_audio - 1);
871 } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) {
872 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
873 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
874 sh_a->format = FOURCC_SPEEX;
875 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
876 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
877 sh_a->wf->wFormatTag = sh_a->format;
878 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
879 sh_a->wf->nBlockAlign = 0;
880 sh_a->wf->wBitsPerSample = 16;
881 sh_a->samplesize = 2;
882 sh_a->wf->cbSize = pack.bytes;
883 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
885 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
886 ogg_d->subs[ogg_d->num_sub].speex = 1;
887 ogg_d->subs[ogg_d->num_sub].id = n_audio;
888 n_audio++;
889 mp_msg(MSGT_DEMUX, MSGL_INFO,
890 "[Ogg] stream %d: audio (Speex), -aid %d\n",
891 ogg_d->num_sub, n_audio - 1);
893 // check for Theora
894 #ifdef CONFIG_OGGTHEORA
895 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
896 int errorCode = 0;
897 theora_info inf;
898 theora_comment cc;
900 theora_info_init (&inf);
901 theora_comment_init (&cc);
903 errorCode = theora_decode_header (&inf, &cc, &pack);
904 if (errorCode) {
905 mp_msg(MSGT_DEMUX, MSGL_ERR,
906 "Theora header parsing failed: %i \n", errorCode);
907 } else {
908 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
910 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
911 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
912 sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA;
913 sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator;
914 sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator;
915 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
916 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
917 sh_v->bih->biBitCount = 24;
918 sh_v->bih->biPlanes = 3;
919 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight);
920 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
921 ogg_d->subs[ogg_d->num_sub].theora = 1;
922 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
923 ogg_d->subs[ogg_d->num_sub].id = n_video;
924 n_video++;
925 mp_msg(MSGT_DEMUX, MSGL_INFO,
926 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
927 ogg_d->num_sub,
928 (int)inf.version_major,
929 (int)inf.version_minor,
930 (int)inf.version_subminor,
931 n_video - 1);
932 if (mp_msg_test(MSGT_HEADER, MSGL_V))
933 print_video_header(sh_v->bih, MSGL_V);
935 theora_comment_clear(&cc);
936 theora_info_clear(&inf);
937 #endif /* CONFIG_OGGTHEORA */
938 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
939 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
940 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
941 ogg_d->subs[ogg_d->num_sub].id = n_audio;
942 n_audio++;
943 ogg_d->subs[ogg_d->num_sub].flac = 1;
944 sh_a->wf = NULL;
945 mp_msg(MSGT_DEMUX, MSGL_INFO,
946 "[Ogg] stream %d: audio (FLAC), -aid %d\n",
947 ogg_d->num_sub, n_audio - 1);
948 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
949 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
950 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
951 ogg_d->subs[ogg_d->num_sub].id = n_audio;
952 n_audio++;
953 ogg_d->subs[ogg_d->num_sub].flac = 2;
954 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
955 sh_a->wf->wFormatTag = sh_a->format;
956 sh_a->wf->cbSize = 34;
957 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
958 mp_msg(MSGT_DEMUX, MSGL_INFO,
959 "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
960 ogg_d->num_sub, n_audio - 1);
962 /// Check for old header
963 } else if (pack.bytes >= 142 &&
964 !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) {
966 // Old video header
967 if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) {
968 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
969 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
970 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
971 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69],
972 pack.packet[70], pack.packet[71]);
973 sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001;
974 sh_v->fps = 1 / sh_v->frametime;
975 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176);
976 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180);
977 sh_v->bih->biBitCount = AV_RL16(pack.packet + 182);
978 if (!sh_v->bih->biBitCount)
979 sh_v->bih->biBitCount = 24; // hack, FIXME
980 sh_v->bih->biPlanes = 1;
981 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
983 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
984 ogg_d->subs[ogg_d->num_sub].id = n_video;
985 n_video++;
986 mp_msg(MSGT_DEMUX, MSGL_INFO,
987 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
988 ogg_d->num_sub, pack.packet[68], pack.packet[69],
989 pack.packet[70], pack.packet[71], n_video - 1);
990 if (mp_msg_test(MSGT_HEADER, MSGL_V))
991 print_video_header(sh_v->bih, MSGL_V);
992 // Old audio header
993 } else if (AV_RL32(pack.packet + 96) == 0x05589F81) {
994 unsigned int extra_size;
996 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
997 extra_size = AV_RL16(pack.packet + 140);
998 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
999 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124);
1000 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126);
1001 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128);
1002 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132);
1003 sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136);
1004 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138);
1005 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1006 sh_a->wf->cbSize = extra_size;
1007 if (extra_size > 0)
1008 memcpy(((char *)sh_a->wf) + sizeof(WAVEFORMATEX),
1009 pack.packet + 142, extra_size);
1011 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1012 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1013 n_audio++;
1014 mp_msg(MSGT_DEMUX, MSGL_INFO,
1015 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1016 ogg_d->num_sub, sh_a->format, n_audio - 1);
1017 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1018 print_wave_header(sh_a->wf, MSGL_V);
1019 } else
1020 mp_msg(MSGT_DEMUX, MSGL_WARN,
1021 "Ogg stream %d contains an old header but the header type is unknown\n",
1022 ogg_d->num_sub);
1024 // Check new header
1025 } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
1026 pack.bytes >= (int)sizeof(stream_header) + 1) {
1027 stream_header *st = (stream_header*)(pack.packet + 1);
1028 /// New video header
1029 if (strncmp(st->streamtype, "video", 5) == 0) {
1030 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
1031 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
1032 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
1033 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1],
1034 st->subtype[2], st->subtype[3]);
1035 sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001;
1036 sh_v->fps = 1.0 / sh_v->frametime;
1037 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
1038 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1039 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1040 if (!sh_v->bih->biBitCount)
1041 sh_v->bih->biBitCount = 24; // hack, FIXME
1042 sh_v->bih->biPlanes = 1;
1043 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
1045 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
1046 ogg_d->subs[ogg_d->num_sub].id = n_video;
1047 n_video++;
1048 mp_msg(MSGT_DEMUX, MSGL_INFO,
1049 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1050 ogg_d->num_sub, st->subtype[0], st->subtype[1],
1051 st->subtype[2], st->subtype[3], n_video - 1);
1052 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1053 print_video_header(sh_v->bih, MSGL_V);
1054 /// New audio header
1055 } else if (strncmp(st->streamtype, "audio", 5) == 0) {
1056 char buffer[5];
1057 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1058 unsigned int extra_offset = 0;
1060 memcpy(buffer, st->subtype, 4);
1061 buffer[4] = '\0';
1063 /* Nasty workaround. stream_header.size seems not to contain the real
1064 size in all cases. There are four extra bytes that are unaccounted
1065 for in front of the real codec initialization data _at least_ for
1066 AAC. So far I've only seen those bytes being all 0, so we can
1067 just skip them here. */
1068 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1069 extra_size -= 4;
1070 extra_offset = 4;
1073 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
1074 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
1075 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1076 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1077 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1078 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1079 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1080 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1081 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1082 sh_a->wf->cbSize = extra_size;
1083 if (extra_size)
1084 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),
1085 ((char *)(st+1))+extra_offset, extra_size);
1087 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1088 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1089 n_audio++;
1090 mp_msg(MSGT_DEMUX, MSGL_INFO,
1091 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1092 ogg_d->num_sub, sh_a->format, n_audio - 1);
1093 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1094 print_wave_header(sh_a->wf, MSGL_V);
1096 /// Check for text (subtitles) header
1097 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1098 mp_msg(MSGT_DEMUX, MSGL_INFO,
1099 "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
1100 ogg_d->num_sub, ogg_d->n_text);
1101 ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10;
1102 ogg_d->subs[ogg_d->num_sub].text = 1;
1103 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1104 if (demuxer->sub->id == ogg_d->n_text)
1105 text_id = ogg_d->num_sub;
1106 new_sh_sub(demuxer, ogg_d->n_text);
1107 ogg_d->n_text++;
1108 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids));
1109 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1110 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs));
1111 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1112 //// Unknown header type
1113 } else
1114 mp_msg(MSGT_DEMUX, MSGL_ERR,
1115 "Ogg stream %d has a header marker but is of an unknown type\n",
1116 ogg_d->num_sub);
1117 /// Unknown (invalid ?) header
1118 } else
1119 mp_msg(MSGT_DEMUX, MSGL_ERR,
1120 "Ogg stream %d is of an unknown type\n",
1121 ogg_d->num_sub);
1123 if (sh_a || sh_v) {
1124 demux_stream_t *ds = NULL;
1125 if (sh_a) {
1126 // If the audio stream is not defined we took the first one
1127 if (demuxer->audio->id == -1) {
1128 demuxer->audio->id = n_audio - 1;
1129 //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
1131 /// Is it the stream we want
1132 if (demuxer->audio->id == n_audio - 1) {
1133 demuxer->audio->sh = sh_a;
1134 sh_a->ds = demuxer->audio;
1135 ds = demuxer->audio;
1136 audio_id = ogg_d->num_sub;
1139 if (sh_v) {
1140 /// Also for video
1141 if (demuxer->video->id == -1) {
1142 demuxer->video->id = n_video - 1;
1143 //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
1145 if (demuxer->video->id == n_video - 1) {
1146 demuxer->video->sh = sh_v;
1147 sh_v->ds = demuxer->video;
1148 ds = demuxer->video;
1149 video_id = ogg_d->num_sub;
1152 /// Add the header packets if the stream isn't seekable
1153 if (ds && !s->end_pos) {
1154 /// Finish the page, otherwise packets will be lost
1155 do {
1156 demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub],
1157 ogg_d->num_sub, &pack);
1158 } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1);
1161 ogg_d->num_sub++;
1164 if (!n_video && !n_audio) {
1165 goto err_out;
1168 if (!n_video || video_id < 0)
1169 demuxer->video->id = -2;
1170 else
1171 demuxer->video->id = video_id;
1172 if (!n_audio || audio_id < 0)
1173 demuxer->audio->id = -2;
1174 else
1175 demuxer->audio->id = audio_id;
1176 /* Disable the subs only if there are no text streams at all.
1177 Otherwise the stream to display might be chosen later when the comment
1178 packet is encountered and the user used -slang instead of -sid. */
1179 if (!ogg_d->n_text)
1180 demuxer->sub->id = -2;
1181 else if (text_id >= 0) {
1182 demuxer->sub->id = text_id;
1183 mp_msg(MSGT_DEMUX, MSGL_V,
1184 "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1187 ogg_d->final_granulepos = 0;
1188 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1189 if (!s->end_pos) {
1190 demuxer->seekable = 0;
1191 } else {
1192 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1193 demuxer->movi_end = s->end_pos;
1194 demuxer->seekable = 1;
1195 demux_ogg_scan_stream(demuxer);
1197 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1198 ogg_d->initial_granulepos = 0;
1199 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1201 mp_msg(MSGT_DEMUX, MSGL_V,
1202 "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
1203 n_audio, n_audio > 1 ? "s" : "",
1204 n_video, n_video > 1 ? "s" : "",
1205 ogg_d->n_text, ogg_d->n_text > 1 ? "s" : "");
1207 sh_a = demuxer->audio->sh;
1208 if (sh_a && sh_a->format == FOURCC_VORBIS)
1209 fixup_vorbis_wf(sh_a, ogg_d);
1211 return DEMUXER_TYPE_OGG;
1213 err_out:
1214 return 0;
1217 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds)
1219 ogg_demuxer_t *ogg_d;
1220 stream_t *s;
1221 demux_stream_t *ds;
1222 ogg_sync_state *sync;
1223 ogg_stream_state *os;
1224 ogg_page *page;
1225 ogg_packet pack;
1226 int np = 0, id=0;
1228 s = d->stream;
1229 ogg_d = d->priv;
1230 sync = &ogg_d->sync;
1231 page = &ogg_d->page;
1233 /// Find the stream we are working on
1234 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1235 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n");
1236 return 0;
1239 while (1) {
1240 np = 0;
1241 ds = NULL;
1242 /// Try to get some packet from the current page
1243 while ((np = ogg_stream_packetout(os, &pack)) != 1) {
1244 /// No packet we go the next page
1245 if (np == 0) {
1246 while (1) {
1247 int pa, len;
1248 char *buf;
1250 ogg_d->pos += ogg_d->last_size;
1251 /// Get the next page from the physical stream
1252 while ((pa = ogg_sync_pageseek(sync, page)) <= 0) {
1253 /// Error : we skip some bytes
1254 if (pa < 0) {
1255 mp_msg(MSGT_DEMUX, MSGL_WARN,
1256 "Ogg : Page out not synced, we skip some bytes\n");
1257 ogg_d->pos -= pa;
1258 continue;
1260 /// We need more data
1261 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1262 len = stream_read(s, buf, BLOCK_SIZE);
1263 if (len == 0 && s->eof) {
1264 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n");
1265 return 0;
1267 ogg_sync_wrote(sync, len);
1268 } /// Page loop
1269 ogg_d->last_size = pa;
1270 /// Find the page's logical stream
1271 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1272 mp_msg(MSGT_DEMUX, MSGL_ERR,
1273 "Ogg demuxer error : we met an unknown stream\n");
1274 return 0;
1276 /// Take the page
1277 if (ogg_stream_pagein(os, page) == 0)
1278 break;
1279 /// Page was invalid => retry
1280 mp_msg(MSGT_DEMUX, MSGL_WARN,
1281 "Ogg demuxer : got invalid page !!!!!\n");
1282 ogg_d->pos += ogg_d->last_size;
1284 } else /// Packet was corrupted
1285 mp_msg(MSGT_DEMUX, MSGL_WARN,
1286 "Ogg : bad packet in stream %d\n", id);
1287 } /// Packet loop
1289 /// Is the actual logical stream in use ?
1290 if (id == d->audio->id)
1291 ds = d->audio;
1292 else if (id == d->video->id)
1293 ds = d->video;
1294 else if (ogg_d->subs[id].text)
1295 ds = d->sub;
1297 if (ds) {
1298 if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack))
1299 continue; /// Unuseful packet, get another
1300 d->filepos = ogg_d->pos;
1301 return 1;
1303 } /// while (1)
1306 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1307 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1308 demuxer_t *init_avi_with_ogg(demuxer_t *demuxer)
1310 struct MPOpts *opts = demuxer->opts;
1311 demuxer_t *od;
1312 ogg_demuxer_t *ogg_d;
1313 stream_t *s;
1314 uint32_t hdrsizes[3];
1315 demux_packet_t *dp;
1316 sh_audio_t *sh_audio = demuxer->audio->sh;
1317 int np;
1318 uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
1319 int i;
1320 unsigned char *p = NULL, *buf;
1321 int plen;
1323 /// Check that the cbSize is big enough for the following reads
1324 if (sh_audio->wf->cbSize < 22 + 3 * 4) {
1325 mp_msg(MSGT_DEMUX, MSGL_ERR,
1326 "AVI Ogg : Initial audio header is too small !!!!!\n");
1327 goto fallback;
1329 /// Get the size of the 3 header packet
1330 extradata += 22;
1331 for (i = 0; i < 3; i++) {
1332 hdrsizes[i] = AV_RL32(extradata);
1333 extradata += 4;
1335 // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
1337 /// Check the size
1338 if (sh_audio->wf->cbSize < 22 + 3 * 4 + hdrsizes[0] + hdrsizes[1] + hdrsizes[2]) {
1339 mp_msg(MSGT_DEMUX, MSGL_ERR,
1340 "AVI Ogg : Audio header is too small !!!!!\n");
1341 goto fallback;
1344 // Build the ogg demuxer private datas
1345 ogg_d = calloc(1, sizeof(*ogg_d));
1346 ogg_d->num_sub = 1;
1347 ogg_d->subs = malloc(sizeof(*ogg_d->subs));
1348 ogg_d->subs[0].vorbis = 1;
1350 // Init the ogg physical stream
1351 ogg_sync_init(&ogg_d->sync);
1353 // Get the first page of the stream : we assume there only 1 logical stream
1354 while ((np = ogg_sync_pageout(&ogg_d->sync, &ogg_d->page)) <= 0 ) {
1355 if (np < 0) {
1356 mp_msg(MSGT_DEMUX, MSGL_ERR,
1357 "AVI Ogg error : Can't init using first stream packets\n");
1358 free(ogg_d);
1359 goto fallback;
1361 // Add some data
1362 plen = ds_get_packet(demuxer->audio, &p);
1363 buf = ogg_sync_buffer(&ogg_d->sync, plen);
1364 memcpy(buf, p, plen);
1365 ogg_sync_wrote(&ogg_d->sync, plen);
1367 // Init the logical stream
1368 mp_msg(MSGT_DEMUX, MSGL_DBG2,
1369 "AVI Ogg found page with serial %d\n",
1370 ogg_page_serialno(&ogg_d->page));
1371 ogg_stream_init(&ogg_d->subs[0].stream, ogg_page_serialno(&ogg_d->page));
1372 // Write the page
1373 ogg_stream_pagein(&ogg_d->subs[0].stream, &ogg_d->page);
1375 // Create the ds_stream and the ogg demuxer
1376 s = new_ds_stream(demuxer->audio);
1377 od = new_demuxer(opts, s, DEMUXER_TYPE_OGG, 0, -2, -2, NULL);
1379 /// Add the header packets in the ogg demuxer audio stream
1380 for (i = 0; i < 3; i++) {
1381 dp = new_demux_packet(hdrsizes[i]);
1382 memcpy(dp->buffer, extradata, hdrsizes[i]);
1383 ds_add_packet(od->audio, dp);
1384 extradata += hdrsizes[i];
1387 // Finish setting up the ogg demuxer
1388 od->priv = ogg_d;
1389 sh_audio = new_sh_audio(od, 0);
1390 od->audio->id = 0;
1391 od->video->id = -2;
1392 od->audio->sh = sh_audio;
1393 sh_audio->ds = od->audio;
1394 sh_audio->format = FOURCC_VORBIS;
1395 fixup_vorbis_wf(sh_audio, ogg_d);
1397 /// Return the joined demuxers
1398 return new_demuxers_demuxer(demuxer, od, demuxer);
1400 fallback:
1401 demuxer->audio->id = -2;
1402 return demuxer;
1406 static void demux_ogg_seek(demuxer_t *demuxer, float rel_seek_secs,
1407 float audio_delay, int flags)
1409 ogg_demuxer_t *ogg_d = demuxer->priv;
1410 ogg_sync_state *sync = &ogg_d->sync;
1411 ogg_page* page= &ogg_d->page;
1412 ogg_stream_state *oss;
1413 ogg_stream_t *os;
1414 demux_stream_t *ds;
1415 ogg_packet op;
1416 float rate;
1417 int i, sp, first, precision = 1, do_seek = 1;
1418 vorbis_info *vi = NULL;
1419 int64_t gp = 0, old_gp;
1420 off_t pos, old_pos;
1421 int np;
1422 int is_gp_valid;
1423 float pts;
1424 int is_keyframe;
1425 int samplesize = 1;
1426 ogg_int64_t granulepos_orig;
1428 if (demuxer->video->id >= 0) {
1429 ds = demuxer->video;
1430 rate = ogg_d->subs[ds->id].samplerate;
1431 } else {
1432 ds = demuxer->audio;
1433 os = &ogg_d->subs[ds->id];
1434 vi = &(os->vi);
1435 rate = (float)vi->rate;
1436 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1439 os = &ogg_d->subs[ds->id];
1440 oss = &os->stream;
1442 old_gp = os->lastpos;
1443 old_pos = ogg_d->pos;
1445 //calculate the granulepos to seek to
1446 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1447 if (flags & SEEK_FACTOR) {
1448 if (ogg_d->duration > 0)
1449 gp += ogg_d->duration * rel_seek_secs;
1450 else
1451 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1452 } else
1453 gp += rel_seek_secs * rate;
1454 if (gp < 0)
1455 gp = 0;
1457 //calculate the filepos to seek to
1458 if (ogg_d->syncpoints) {
1459 for (sp = 0; sp < ogg_d->num_syncpoint; sp++)
1460 if (ogg_d->syncpoints[sp].granulepos >= gp)
1461 break;
1463 if (sp >= ogg_d->num_syncpoint)
1464 return;
1465 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp - 1].granulepos)
1466 sp--;
1467 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1468 if (sp > 0 && gp < os->lastpos)
1469 sp--;
1470 if (sp < ogg_d->num_syncpoint - 1 && gp > os->lastpos)
1471 sp++;
1473 pos = ogg_d->syncpoints[sp].page_pos;
1474 precision = 0;
1475 } else {
1476 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1477 if (flags & SEEK_FACTOR)
1478 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1479 else {
1480 if (ogg_d->duration > 0) {
1481 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1482 } else if (os->lastpos > 0) {
1483 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1486 if (pos < 0)
1487 pos = 0;
1488 if (pos > (demuxer->movi_end - demuxer->movi_start))
1489 pos = demuxer->movi_end - demuxer->movi_start;
1490 } // if (ogg_d->syncpoints)
1492 while (1) {
1493 if (do_seek) {
1494 stream_seek(demuxer->stream, pos+demuxer->movi_start);
1495 ogg_sync_reset(sync);
1496 for (i = 0; i < ogg_d->num_sub; i++) {
1497 ogg_stream_reset(&ogg_d->subs[i].stream);
1498 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1500 ogg_d->pos = pos;
1501 ogg_d->last_size = 0;
1502 /* we just guess that we reached correct granulepos, in case a
1503 subsequent search occurs before we read a valid granulepos */
1504 os->lastpos = gp;
1505 first = !(ogg_d->syncpoints);
1506 do_seek=0;
1508 ogg_d->pos += ogg_d->last_size;
1509 ogg_d->last_size = 0;
1510 np = ogg_sync_pageseek(sync, page);
1512 if (np < 0)
1513 ogg_d->pos -= np;
1514 if (np <= 0) { // We need more data
1515 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1516 int len = stream_read(demuxer->stream, buf, BLOCK_SIZE);
1518 if (len == 0 && demuxer->stream->eof) {
1519 mp_msg(MSGT_DEMUX, MSGL_V, "EOF while trying to seek !!!!\n");
1520 return;
1522 ogg_sync_wrote(sync, len);
1523 continue;
1525 ogg_d->last_size = np;
1526 if (ogg_page_serialno(page) != oss->serialno)
1527 continue;
1529 if (ogg_stream_pagein(oss, page) != 0)
1530 continue;
1532 while (1) {
1533 np = ogg_stream_packetout(oss, &op);
1534 if (np < 0)
1535 continue;
1536 else if (np == 0)
1537 break;
1538 if (first) { /* Discard the first packet as it's probably broken,
1539 and we don't have any other means to decide whether it is
1540 complete or not. */
1541 first = 0;
1542 break;
1544 is_gp_valid = (op.granulepos >= 0);
1545 granulepos_orig=op.granulepos;
1546 demux_ogg_read_packet(os, &op, &pts, &is_keyframe, samplesize);
1547 if (precision && is_gp_valid) {
1548 precision--;
1549 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1550 //prepare another seek because we are off by more than 1s
1551 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1552 if (pos < 0)
1553 pos = 0;
1554 if (pos < demuxer->movi_end - demuxer->movi_start) {
1555 do_seek=1;
1556 break;
1560 if (is_gp_valid && pos > 0 && old_gp > gp
1561 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1562 /* prepare another seek because looking for a syncpoint
1563 destroyed the backward search */
1564 pos = old_pos - 1.5 * (old_pos - pos);
1565 if (pos < 0)
1566 pos = 0;
1567 if (pos < demuxer->movi_end - demuxer->movi_start) {
1568 do_seek=1;
1569 break;
1572 if (!precision && (is_keyframe || os->vorbis || os->speex)) {
1573 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1574 vo_sub = &ogg_sub;
1575 vo_osd_changed(OSDTYPE_SUBTITLE);
1577 op.granulepos=granulepos_orig;
1578 demux_ogg_add_packet(ds, os, ds->id, &op);
1579 return;
1584 mp_msg(MSGT_DEMUX, MSGL_ERR, "Can't find the good packet :(\n");
1587 static void demux_close_ogg(demuxer_t *demuxer)
1589 ogg_demuxer_t *ogg_d = demuxer->priv;
1590 ogg_stream_t *os = NULL;
1591 int i;
1593 if (!ogg_d)
1594 return;
1596 #ifdef CONFIG_ICONV
1597 subcp_close();
1598 #endif
1600 ogg_sync_clear(&ogg_d->sync);
1601 if (ogg_d->subs) {
1602 for (i = 0; i < ogg_d->num_sub; i++) {
1603 os = &ogg_d->subs[i];
1604 ogg_stream_clear(&os->stream);
1605 if (os->vi_initialized)
1606 vorbis_info_clear(&os->vi);
1608 free(ogg_d->subs);
1610 if (ogg_d->syncpoints)
1611 free(ogg_d->syncpoints);
1612 if (ogg_d->text_ids)
1613 free(ogg_d->text_ids);
1614 if (ogg_d->text_langs) {
1615 for (i = 0; i < ogg_d->n_text; i++)
1616 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1617 free(ogg_d->text_langs);
1619 free(ogg_d);
1622 static int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg)
1624 ogg_demuxer_t *ogg_d = demuxer->priv;
1625 ogg_stream_t *os;
1626 float rate;
1628 if (demuxer->video->id >= 0) {
1629 os = &ogg_d->subs[demuxer->video->id];
1630 rate = os->samplerate;
1631 } else {
1632 os = &ogg_d->subs[demuxer->audio->id];
1633 rate = os->vi.rate;
1636 switch(cmd) {
1637 case DEMUXER_CTRL_GET_TIME_LENGTH:
1638 if (ogg_d->duration <= 0)
1639 return DEMUXER_CTRL_DONTKNOW;
1640 *(double *)arg = (double)(ogg_d->duration) / rate;
1641 return DEMUXER_CTRL_GUESS;
1643 case DEMUXER_CTRL_GET_PERCENT_POS:
1644 if (ogg_d->duration <= 0)
1645 return DEMUXER_CTRL_DONTKNOW;
1646 *(int *)arg = ((os->lastpos - ogg_d->initial_granulepos) * 100) / ogg_d->duration;
1647 return DEMUXER_CTRL_OK;
1649 default:
1650 return DEMUXER_CTRL_NOTIMPL;
1654 const demuxer_desc_t demuxer_desc_ogg = {
1655 "Ogg demuxer",
1656 "ogg",
1657 "Ogg",
1658 "?",
1660 DEMUXER_TYPE_OGG,
1661 1, // safe autodetect
1662 demux_ogg_open,
1663 demux_ogg_fill_buffer,
1664 NULL,
1665 demux_close_ogg,
1666 demux_ogg_seek,
1667 demux_ogg_control