Merge svn changes up to r31050
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blobe872ad5156543742fdb728b0b78d3061f35979e0
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 extern char *dvdsub_lang, *audio_lang;
168 //-------- subtitle support - should be moved to decoder layer, and queue
169 // - subtitles up in demuxer buffer...
171 #include "subreader.h"
172 #include "libvo/sub.h"
173 #define OGG_SUB_MAX_LINE 128
175 static subtitle ogg_sub;
176 //FILE* subout;
178 static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
180 int lcv;
181 char *packet = pack->packet;
183 if (pack->bytes < 4)
184 return;
185 mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
186 (unsigned char)packet[0],
187 (unsigned char)packet[1],
188 (unsigned char)packet[2],
189 &packet[3]);
191 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
192 // Find data start
193 double endpts = MP_NOPTS_VALUE;
194 int32_t duration = 0;
195 int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i;
197 hdrlen |= (*packet & PACKET_LEN_BITS2) << 1;
198 lcv = 1 + hdrlen;
199 if (pack->bytes < lcv)
200 return;
201 for (i = hdrlen; i > 0; i--) {
202 duration <<= 8;
203 duration |= (unsigned char)packet[i];
205 if (hdrlen > 0 && duration > 0) {
206 float pts;
208 if (pack->granulepos == -1)
209 pack->granulepos = os->lastpos + os->lastsize;
210 pts = (float)pack->granulepos / (float)os->samplerate;
211 endpts = 1.0 + pts + (float)duration / 1000.0;
213 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
214 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
217 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n",
218 ogg_sub.lines, ogg_sub.text[0]);
219 #ifdef CONFIG_ICONV
220 subcp_recode(&ogg_sub);
221 #endif
222 vo_sub = &ogg_sub;
223 vo_osd_changed(OSDTYPE_SUBTITLE);
227 // get the logical stream of the current page
228 // fill os if non NULL and return the stream id
229 static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d,
230 ogg_stream_state **os)
232 int id, s_no;
233 ogg_page *page = &ogg_d->page;
235 s_no = ogg_page_serialno(page);
237 for (id = 0; id < ogg_d->num_sub; id++)
238 if (s_no == ogg_d->subs[id].stream.serialno)
239 break;
241 if (id == ogg_d->num_sub) {
242 // If we have only one vorbis stream allow the stream id to change
243 // it's normal on radio stream (each song have an different id).
244 // But we (or the codec?) should check that the samplerate, etc
245 // doesn't change (for radio stream it's ok)
246 if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
247 ogg_stream_reset(&ogg_d->subs[0].stream);
248 ogg_stream_init(&ogg_d->subs[0].stream, s_no);
249 id = 0;
250 } else
251 return -1;
254 if (os)
255 *os = &ogg_d->subs[id].stream;
257 return id;
260 static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack,
261 float *pts, int *flags,
262 int samplesize)
264 unsigned char *data = pack->packet;
265 int size = pack->bytes;
267 *pts = MP_NOPTS_VALUE;
268 *flags = 0;
270 if (os->vorbis) {
271 if (*pack->packet & PACKET_TYPE_HEADER) {
272 os->hdr_packets++;
273 } else {
274 vorbis_info *vi;
275 int32_t blocksize = 0;
277 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
278 vi = os->vi_initialized ? &os->vi : NULL;
279 if (vi)
280 blocksize = vorbis_packet_blocksize(vi, pack) / samplesize;
281 // Calculate the timestamp if the packet don't have any
282 if (pack->granulepos == -1) {
283 pack->granulepos = os->lastpos;
284 if (os->lastsize > 0)
285 pack->granulepos += os->lastsize;
286 } else
287 *flags = 1;
288 if (vi)
289 *pts = pack->granulepos / (float)vi->rate;
290 os->lastsize = blocksize;
291 os->lastpos = pack->granulepos;
293 } else if (os->speex) {
294 // whole packet (default)
295 # ifdef CONFIG_OGGTHEORA
296 } else if (os->theora) {
297 /* we pass complete packets to theora, mustn't strip the header! */
298 os->lastsize = 1;
300 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
301 have theora_state st, until all header packets were passed to the
302 decoder. */
303 if (!size || !(*data&0x80)) {
304 int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1);
305 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
307 if (pack->granulepos >= 0) {
308 os->lastpos = pack->granulepos >> keyframe_granule_shift;
309 os->lastpos += pack->granulepos & iframemask;
310 *flags = (pack->granulepos & iframemask) == 0;
311 } else {
312 os->lastpos++;
314 pack->granulepos = os->lastpos;
315 *pts = (double)os->lastpos / (double)os->samplerate;
317 #endif /* CONFIG_OGGTHEORA */
318 } else if (os->flac) {
319 /* we pass complete packets to flac, mustn't strip the header! */
320 if (os->flac == 2 && pack->packet[0] != 0xff)
321 return NULL;
322 } else {
323 if (*pack->packet & PACKET_TYPE_HEADER) {
324 os->hdr_packets++;
325 } else {
326 // Find data start
327 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6;
329 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1;
330 data = pack->packet + 1 + hdrlen;
331 // Calculate the timestamp
332 if (pack->granulepos == -1)
333 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
334 // If we already have a timestamp it can be a syncpoint
335 if (*pack->packet & PACKET_IS_SYNCPOINT)
336 *flags = 1;
337 *pts = pack->granulepos / os->samplerate;
338 // Save the packet length and timestamp
339 os->lastsize = 0;
340 while (hdrlen) {
341 os->lastsize <<= 8;
342 os->lastsize |= pack->packet[hdrlen];
343 hdrlen--;
345 os->lastpos = pack->granulepos;
348 return data;
351 // check if clang has substring from comma separated langlist
352 static int demux_ogg_check_lang(const char *clang, const char *langlist)
354 const char *c;
356 if (!langlist || !*langlist)
357 return 0;
358 while ((c = strchr(langlist, ','))) {
359 if (!strncasecmp(clang, langlist, c - langlist))
360 return 1;
361 langlist = &c[1];
363 if (!strncasecmp(clang, langlist, strlen(langlist)))
364 return 1;
365 return 0;
368 /** \brief Change the current subtitle stream and return its ID.
370 \param demuxer The demuxer whose subtitle stream will be changed.
371 \param new_num The number of the new subtitle track. The number must be
372 between 0 and ogg_d->n_text - 1.
374 \returns The Ogg stream number ( = page serial number) of the newly selected
375 track.
377 static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
379 ogg_demuxer_t *ogg_d = demuxer->priv;
380 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
383 /** \brief Translate the ogg track number into the subtitle number.
384 * \param demuxer The demuxer about whose subtitles we are inquiring.
385 * \param id The ogg track number of the subtitle track.
387 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id)
389 ogg_demuxer_t *ogg_d = demuxer->priv;
390 int i;
392 for (i = 0; i < ogg_d->n_text; i++)
393 if (ogg_d->text_ids[i] == id)
394 return i;
395 return -1;
398 /// Try to print out comments and also check for LANGUAGE= tag
399 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os,
400 int id, vorbis_comment *vc)
402 const char *hdr, *val;
403 char **cmt = vc->user_comments;
404 int index, i;
405 ogg_demuxer_t *ogg_d = d->priv;
406 static const struct table {
407 const char *ogg;
408 const char *mp;
409 } table[] = {
410 { "ENCODED_USING", "Software" },
411 { "ENCODER_URL", "Encoder URL" },
412 { "TITLE", "Title" },
413 { "ARTIST", "Artist" },
414 { "COMMENT", "Comments" },
415 { "DATE", "Creation Date" },
416 { "GENRE", "Genre" },
417 { "ALBUM", "Album" },
418 { "TRACKNUMBER", "Track" },
419 { NULL, NULL },
422 while (*cmt) {
423 hdr = NULL;
424 if (!strncasecmp(*cmt, "LANGUAGE=", 9)) {
425 val = *cmt + 9;
426 if (ogg_d->subs[id].text)
427 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n",
428 ogg_d->subs[id].id, val);
429 else if (id != d->video->id)
430 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n",
431 ogg_d->subs[id].id, val);
432 if (ogg_d->subs[id].text)
433 mp_msg(MSGT_DEMUX, MSGL_INFO,
434 "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
435 ogg_d->subs[id].id, val);
436 // copy this language name into the array
437 index = demux_ogg_sub_reverse_id(d, id);
438 if (index >= 0) {
439 sh_sub_t *sh;
441 // in case of malicious files with more than one lang per track:
442 if (ogg_d->text_langs[index])
443 free(ogg_d->text_langs[index]);
444 ogg_d->text_langs[index] = strdup(val);
445 sh = d->s_streams[index];
446 if (sh && sh->lang)
447 free(sh->lang);
448 if (sh)
449 sh->lang = strdup(val);
451 // check for -slang if subs are uninitialized yet
452 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang)) {
453 d->sub->id = index;
454 d->opts->sub_id = index;
455 mp_msg(MSGT_DEMUX, MSGL_V,
456 "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
457 id, val);
459 else
460 hdr = "Language";
462 else {
463 for (i = 0; table[i].ogg; i++) {
464 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
465 (*cmt)[strlen(table[i].ogg)] == '=') {
466 hdr = table[i].mp;
467 val = *cmt + strlen(table[i].ogg) + 1;
471 if (hdr)
472 demux_info_add(d, hdr, val);
473 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
474 cmt++;
478 /// Calculate the timestamp and add the packet to the demux stream
479 // return 1 if the packet was added, 0 otherwise
480 static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
481 int id, ogg_packet *pack)
483 demuxer_t *d = ds->demuxer;
484 demux_packet_t *dp;
485 unsigned char *data;
486 float pts = 0;
487 int flags = 0;
488 int samplesize = 1;
490 // If packet is an comment header then we try to get comments at first
491 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
492 vorbis_info vi;
493 vorbis_comment vc;
495 vorbis_info_init(&vi);
496 vorbis_comment_init(&vc);
497 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
498 if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
499 demux_ogg_check_comments(d, os, id, &vc);
500 vorbis_comment_clear(&vc);
501 vorbis_info_clear(&vi);
503 if (os->text) {
504 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
505 demux_ogg_add_sub(os, pack);
506 return 0;
508 if (os->speex) {
509 // discard first two packets, they contain the header and comment
510 if (os->hdr_packets < 2) {
511 os->hdr_packets++;
512 return 0;
514 } else {
515 // If packet is an header we jump it except for vorbis and theora
516 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
517 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
518 // handled differently for each and every stream type. The joy! The joy!
519 if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
520 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
521 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
522 return 0;
525 // For vorbis packet the packet is the data, for other codec we must jump
526 // the header
527 if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
528 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
530 data = demux_ogg_read_packet(os, pack, &pts, &flags, samplesize);
531 if (!data)
532 return 0;
534 /// Clear subtitles if necessary (for broken files)
535 if (sub_clear_text(&ogg_sub, pts)) {
536 vo_sub = &ogg_sub;
537 vo_osd_changed(OSDTYPE_SUBTITLE);
539 /// Send the packet
540 dp = new_demux_packet(pack->bytes - (data - pack->packet));
541 memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
542 dp->pts = pts;
543 dp->flags = flags;
544 ds_add_packet(ds, dp);
545 mp_msg(MSGT_DEMUX, MSGL_DBG2,
546 "New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
547 dp, ds, pts, dp->len, flags);
548 return 1;
551 /// if -forceidx build a table of all syncpoints to make seeking easier
552 /// otherwise try to get at least the final_granulepos
553 static void demux_ogg_scan_stream(demuxer_t *demuxer)
555 ogg_demuxer_t *ogg_d = demuxer->priv;
556 stream_t *s = demuxer->stream;
557 ogg_sync_state *sync = &ogg_d->sync;
558 ogg_page *page = &ogg_d->page;
559 ogg_stream_state *oss;
560 ogg_stream_t *os;
561 ogg_packet op;
562 int np, sid, p, samplesize = 1;
563 off_t pos, last_pos;
565 pos = last_pos = demuxer->movi_start;
567 // Reset the stream
568 stream_seek(s, demuxer->movi_start);
569 ogg_sync_reset(sync);
571 // Get the serial number of the stream we use
572 if (demuxer->video->id >= 0) {
573 sid = demuxer->video->id;
574 } else if (demuxer->audio->id >= 0) {
575 sid = demuxer->audio->id;
576 if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
577 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
578 } else
579 return;
580 os = &ogg_d->subs[sid];
581 oss = &os->stream;
583 while (1) {
584 np = ogg_sync_pageseek(sync, page);
585 if (np < 0) { // We had to skip some bytes
586 if (index_mode == 2)
587 mp_msg(MSGT_DEMUX, MSGL_ERR,
588 "Bad page sync while building syncpoints table (%d)\n",
589 -np);
590 pos += -np;
591 continue;
593 if (np <= 0) { // We need more data
594 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
595 int len = stream_read(s, buf, BLOCK_SIZE);
597 if (len == 0 && s->eof)
598 break;
599 ogg_sync_wrote(sync, len);
600 continue;
602 // The page is ready
603 //ogg_sync_pageout(sync, page);
604 if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
605 pos += np;
606 continue;
608 if (ogg_stream_pagein(oss, page) != 0) {
609 mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
610 pos += np;
611 continue;
613 p = 0;
614 while (ogg_stream_packetout(oss, &op) == 1) {
615 float pts;
616 int flags;
618 demux_ogg_read_packet(os, &op, &pts, &flags, samplesize);
619 if (op.granulepos >= 0) {
620 ogg_d->final_granulepos = op.granulepos;
621 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
622 ogg_d->initial_granulepos = op.granulepos;
623 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
624 //the 270000 are just a wild guess
625 stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
626 ogg_sync_reset(sync);
627 continue;
631 if (index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
632 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1)
633 break;
634 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t));
635 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
636 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
637 ogg_d->num_syncpoint++;
639 p++;
641 if (p > 1 || (p == 1 && !ogg_page_continued(page)))
642 last_pos = pos;
643 pos += np;
644 if (index_mode == 2)
645 mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r",
646 (int)(pos * 100 / s->end_pos));
649 if (index_mode == 2) {
650 mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
651 mp_msg(MSGT_DEMUX, MSGL_V,
652 "Ogg syncpoints table builed: %d syncpoints\n",
653 ogg_d->num_syncpoint);
656 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n",
657 ogg_d->final_granulepos);
659 stream_reset(s);
660 stream_seek(s, demuxer->movi_start);
661 ogg_sync_reset(sync);
662 for (np = 0; np < ogg_d->num_sub; np++) {
663 ogg_stream_reset(&ogg_d->subs[np].stream);
664 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
667 // Get the first page
668 while (1) {
669 np = ogg_sync_pageout(sync, page);
670 if (np <= 0) { // We need more data
671 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
672 int len = stream_read(s, buf, BLOCK_SIZE);
674 if (len == 0 && s->eof) {
675 mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n");
676 break;
678 ogg_sync_wrote(sync, len);
679 continue;
681 demux_ogg_get_page_stream(ogg_d, &oss);
682 ogg_stream_pagein(oss, page);
683 break;
687 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
689 int i, offset;
690 int ris, init_error = 0;
691 ogg_packet op[3];
692 unsigned char *buf[3];
693 unsigned char *ptr;
694 unsigned int len;
695 ogg_stream_t *os = &od->subs[sh->ds->id];
696 vorbis_comment vc;
698 vorbis_info_init(&os->vi);
699 vorbis_comment_init(&vc);
700 for (i = 0; i < 3; i++) {
701 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
702 mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
703 if (op[i].bytes < 0) {
704 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
705 return;
707 buf[i] = malloc(op[i].bytes);
708 if (!buf[i])
709 return;
710 memcpy(buf[i], op[i].packet, op[i].bytes);
712 op[i].b_o_s = (i == 0);
713 ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]);
714 if (ris < 0) {
715 init_error = 1;
716 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
719 vorbis_comment_clear(&vc);
720 if (!init_error)
721 os->vi_initialized = 1;
723 len = op[0].bytes + op[1].bytes + op[2].bytes;
724 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len / 255 + 64);
725 ptr = (unsigned char*)(sh->wf + 1);
727 ptr[0] = 2;
728 offset = 1;
729 offset += store_ughvlc(&ptr[offset], op[0].bytes);
730 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset);
731 offset += store_ughvlc(&ptr[offset], op[1].bytes);
732 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset);
733 for (i = 0; i < 3; i++) {
734 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
735 memcpy(&ptr[offset], buf[i], op[i].bytes);
736 offset += op[i].bytes;
738 sh->wf->cbSize = offset;
739 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
740 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
742 if (op[0].bytes >= 29) {
743 unsigned int br;
744 int nombr, minbr, maxbr;
746 ptr = buf[0];
747 sh->channels = ptr[11];
748 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
749 maxbr = AV_RL32(&ptr[16]); //max
750 nombr = AV_RL32(&ptr[20]); //nominal
751 minbr = AV_RL32(&ptr[24]); //minimum
753 if (maxbr == -1)
754 maxbr = 0;
755 if (nombr == -1)
756 nombr = 0;
757 if (minbr == -1)
758 minbr = 0;
760 br = maxbr / 8;
761 if (!br)
762 br = nombr / 8;
763 if (!br)
764 br = minbr / 8;
765 sh->wf->nAvgBytesPerSec = br;
766 sh->wf->wBitsPerSample = 16;
767 sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8;
769 mp_msg(MSGT_DEMUX, MSGL_V,
770 "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
771 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec,
772 maxbr, nombr, minbr);
774 free(buf[2]);
775 free(buf[1]);
776 free(buf[0]);
779 /// Open an ogg physical stream
780 // Not static because it's used also in demuxer_avi.c
781 int demux_ogg_open(demuxer_t *demuxer)
783 ogg_demuxer_t *ogg_d;
784 stream_t *s;
785 char *buf;
786 int np, s_no, n_audio = 0, n_video = 0;
787 int audio_id = -1, video_id = -1, text_id = -1;
788 ogg_sync_state *sync;
789 ogg_page *page;
790 ogg_packet pack;
791 sh_audio_t *sh_a;
792 sh_video_t *sh_v;
794 #ifdef CONFIG_ICONV
795 subcp_open(NULL);
796 #endif
798 s = demuxer->stream;
800 demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d));
801 sync = &ogg_d->sync;
802 page = &ogg_d->page;
804 ogg_sync_init(sync);
806 while (1) {
807 /// Try to get a page
808 ogg_d->pos += ogg_d->last_size;
809 np = ogg_sync_pageseek(sync, page);
810 /// Error
811 if (np < 0) {
812 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n");
813 goto err_out;
815 /// Need some more data
816 if (np == 0) {
817 int len;
819 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
820 len = stream_read(s, buf, BLOCK_SIZE);
821 if (len == 0 && s->eof) {
822 goto err_out;
824 ogg_sync_wrote(sync, len);
825 continue;
827 ogg_d->last_size = np;
828 // We got one page now
830 if (!ogg_page_bos(page)) { // It's not a beginning page
831 // Header parsing end here, we need to get the page otherwise it will be lost
832 int id = demux_ogg_get_page_stream(ogg_d, NULL);
833 if (id >= 0)
834 ogg_stream_pagein(&ogg_d->subs[id].stream, page);
835 else
836 mp_msg(MSGT_DEMUX, MSGL_ERR,
837 "Ogg : Warning found none bos page from unknown stream %d\n",
838 ogg_page_serialno(page));
839 break;
842 /// Init the data structure needed for a logical stream
843 ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1,
844 sizeof(ogg_stream_t));
845 memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t));
846 /// Get the stream serial number
847 s_no = ogg_page_serialno(page);
848 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no);
849 mp_msg(MSGT_DEMUX, MSGL_DBG2,
850 "Ogg : Found a stream with serial=%d\n", s_no);
851 // Take the first page
852 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page);
853 // Get first packet of the page
854 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack);
856 // Reset our vars
857 sh_a = NULL;
858 sh_v = NULL;
860 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
862 // Check for Vorbis
863 if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) {
864 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
865 sh_a->format = FOURCC_VORBIS;
866 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
867 ogg_d->subs[ogg_d->num_sub].id = n_audio;
868 n_audio++;
869 mp_msg(MSGT_DEMUX, MSGL_INFO,
870 "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
871 ogg_d->num_sub, n_audio - 1);
872 } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) {
873 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
874 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
875 sh_a->format = FOURCC_SPEEX;
876 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
877 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
878 sh_a->wf->wFormatTag = sh_a->format;
879 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
880 sh_a->wf->nBlockAlign = 0;
881 sh_a->wf->wBitsPerSample = 16;
882 sh_a->samplesize = 2;
883 sh_a->wf->cbSize = pack.bytes;
884 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
886 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
887 ogg_d->subs[ogg_d->num_sub].speex = 1;
888 ogg_d->subs[ogg_d->num_sub].id = n_audio;
889 n_audio++;
890 mp_msg(MSGT_DEMUX, MSGL_INFO,
891 "[Ogg] stream %d: audio (Speex), -aid %d\n",
892 ogg_d->num_sub, n_audio - 1);
894 // check for Theora
895 #ifdef CONFIG_OGGTHEORA
896 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
897 int errorCode = 0;
898 theora_info inf;
899 theora_comment cc;
901 theora_info_init (&inf);
902 theora_comment_init (&cc);
904 errorCode = theora_decode_header (&inf, &cc, &pack);
905 if (errorCode) {
906 mp_msg(MSGT_DEMUX, MSGL_ERR,
907 "Theora header parsing failed: %i \n", errorCode);
908 } else {
909 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
911 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
912 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
913 sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA;
914 sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator;
915 sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator;
916 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
917 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
918 sh_v->bih->biBitCount = 24;
919 sh_v->bih->biPlanes = 3;
920 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight);
921 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
922 ogg_d->subs[ogg_d->num_sub].theora = 1;
923 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
924 ogg_d->subs[ogg_d->num_sub].id = n_video;
925 n_video++;
926 mp_msg(MSGT_DEMUX, MSGL_INFO,
927 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
928 ogg_d->num_sub,
929 (int)inf.version_major,
930 (int)inf.version_minor,
931 (int)inf.version_subminor,
932 n_video - 1);
933 if (mp_msg_test(MSGT_HEADER, MSGL_V))
934 print_video_header(sh_v->bih, MSGL_V);
936 theora_comment_clear(&cc);
937 theora_info_clear(&inf);
938 #endif /* CONFIG_OGGTHEORA */
939 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
940 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
941 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
942 ogg_d->subs[ogg_d->num_sub].id = n_audio;
943 n_audio++;
944 ogg_d->subs[ogg_d->num_sub].flac = 1;
945 sh_a->wf = NULL;
946 mp_msg(MSGT_DEMUX, MSGL_INFO,
947 "[Ogg] stream %d: audio (FLAC), -aid %d\n",
948 ogg_d->num_sub, n_audio - 1);
949 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
950 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
951 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
952 ogg_d->subs[ogg_d->num_sub].id = n_audio;
953 n_audio++;
954 ogg_d->subs[ogg_d->num_sub].flac = 2;
955 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
956 sh_a->wf->wFormatTag = sh_a->format;
957 sh_a->wf->cbSize = 34;
958 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
959 mp_msg(MSGT_DEMUX, MSGL_INFO,
960 "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
961 ogg_d->num_sub, n_audio - 1);
963 /// Check for old header
964 } else if (pack.bytes >= 142 &&
965 !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) {
967 // Old video header
968 if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) {
969 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
970 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
971 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
972 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69],
973 pack.packet[70], pack.packet[71]);
974 sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001;
975 sh_v->fps = 1 / sh_v->frametime;
976 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176);
977 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180);
978 sh_v->bih->biBitCount = AV_RL16(pack.packet + 182);
979 if (!sh_v->bih->biBitCount)
980 sh_v->bih->biBitCount = 24; // hack, FIXME
981 sh_v->bih->biPlanes = 1;
982 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
984 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
985 ogg_d->subs[ogg_d->num_sub].id = n_video;
986 n_video++;
987 mp_msg(MSGT_DEMUX, MSGL_INFO,
988 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
989 ogg_d->num_sub, pack.packet[68], pack.packet[69],
990 pack.packet[70], pack.packet[71], n_video - 1);
991 if (mp_msg_test(MSGT_HEADER, MSGL_V))
992 print_video_header(sh_v->bih, MSGL_V);
993 // Old audio header
994 } else if (AV_RL32(pack.packet + 96) == 0x05589F81) {
995 unsigned int extra_size;
997 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
998 extra_size = AV_RL16(pack.packet + 140);
999 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
1000 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124);
1001 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126);
1002 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128);
1003 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132);
1004 sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136);
1005 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138);
1006 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1007 sh_a->wf->cbSize = extra_size;
1008 if (extra_size > 0)
1009 memcpy(((char *)sh_a->wf) + sizeof(WAVEFORMATEX),
1010 pack.packet + 142, extra_size);
1012 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1013 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1014 n_audio++;
1015 mp_msg(MSGT_DEMUX, MSGL_INFO,
1016 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1017 ogg_d->num_sub, sh_a->format, n_audio - 1);
1018 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1019 print_wave_header(sh_a->wf, MSGL_V);
1020 } else
1021 mp_msg(MSGT_DEMUX, MSGL_WARN,
1022 "Ogg stream %d contains an old header but the header type is unknown\n",
1023 ogg_d->num_sub);
1025 // Check new header
1026 } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
1027 pack.bytes >= (int)sizeof(stream_header) + 1) {
1028 stream_header *st = (stream_header*)(pack.packet + 1);
1029 /// New video header
1030 if (strncmp(st->streamtype, "video", 5) == 0) {
1031 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
1032 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
1033 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
1034 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1],
1035 st->subtype[2], st->subtype[3]);
1036 sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001;
1037 sh_v->fps = 1.0 / sh_v->frametime;
1038 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
1039 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1040 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1041 if (!sh_v->bih->biBitCount)
1042 sh_v->bih->biBitCount = 24; // hack, FIXME
1043 sh_v->bih->biPlanes = 1;
1044 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
1046 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
1047 ogg_d->subs[ogg_d->num_sub].id = n_video;
1048 n_video++;
1049 mp_msg(MSGT_DEMUX, MSGL_INFO,
1050 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1051 ogg_d->num_sub, st->subtype[0], st->subtype[1],
1052 st->subtype[2], st->subtype[3], n_video - 1);
1053 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1054 print_video_header(sh_v->bih, MSGL_V);
1055 /// New audio header
1056 } else if (strncmp(st->streamtype, "audio", 5) == 0) {
1057 char buffer[5];
1058 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1059 unsigned int extra_offset = 0;
1061 memcpy(buffer, st->subtype, 4);
1062 buffer[4] = '\0';
1064 /* Nasty workaround. stream_header.size seems not to contain the real
1065 size in all cases. There are four extra bytes that are unaccounted
1066 for in front of the real codec initialization data _at least_ for
1067 AAC. So far I've only seen those bytes being all 0, so we can
1068 just skip them here. */
1069 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1070 extra_size -= 4;
1071 extra_offset = 4;
1074 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
1075 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
1076 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1077 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1078 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1079 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1080 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1081 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1082 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1083 sh_a->wf->cbSize = extra_size;
1084 if (extra_size)
1085 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),
1086 ((char *)(st+1))+extra_offset, extra_size);
1088 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1089 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1090 n_audio++;
1091 mp_msg(MSGT_DEMUX, MSGL_INFO,
1092 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1093 ogg_d->num_sub, sh_a->format, n_audio - 1);
1094 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1095 print_wave_header(sh_a->wf, MSGL_V);
1097 /// Check for text (subtitles) header
1098 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1099 mp_msg(MSGT_DEMUX, MSGL_INFO,
1100 "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
1101 ogg_d->num_sub, ogg_d->n_text);
1102 ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10;
1103 ogg_d->subs[ogg_d->num_sub].text = 1;
1104 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1105 if (demuxer->sub->id == ogg_d->n_text)
1106 text_id = ogg_d->num_sub;
1107 new_sh_sub(demuxer, ogg_d->n_text);
1108 ogg_d->n_text++;
1109 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids));
1110 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1111 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs));
1112 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1113 //// Unknown header type
1114 } else
1115 mp_msg(MSGT_DEMUX, MSGL_ERR,
1116 "Ogg stream %d has a header marker but is of an unknown type\n",
1117 ogg_d->num_sub);
1118 /// Unknown (invalid ?) header
1119 } else
1120 mp_msg(MSGT_DEMUX, MSGL_ERR,
1121 "Ogg stream %d is of an unknown type\n",
1122 ogg_d->num_sub);
1124 if (sh_a || sh_v) {
1125 demux_stream_t *ds = NULL;
1126 if (sh_a) {
1127 // If the audio stream is not defined we took the first one
1128 if (demuxer->audio->id == -1) {
1129 demuxer->audio->id = n_audio - 1;
1130 //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
1132 /// Is it the stream we want
1133 if (demuxer->audio->id == n_audio - 1) {
1134 demuxer->audio->sh = sh_a;
1135 sh_a->ds = demuxer->audio;
1136 ds = demuxer->audio;
1137 audio_id = ogg_d->num_sub;
1140 if (sh_v) {
1141 /// Also for video
1142 if (demuxer->video->id == -1) {
1143 demuxer->video->id = n_video - 1;
1144 //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
1146 if (demuxer->video->id == n_video - 1) {
1147 demuxer->video->sh = sh_v;
1148 sh_v->ds = demuxer->video;
1149 ds = demuxer->video;
1150 video_id = ogg_d->num_sub;
1153 /// Add the header packets if the stream isn't seekable
1154 if (ds && !s->end_pos) {
1155 /// Finish the page, otherwise packets will be lost
1156 do {
1157 demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub],
1158 ogg_d->num_sub, &pack);
1159 } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1);
1162 ogg_d->num_sub++;
1165 if (!n_video && !n_audio) {
1166 goto err_out;
1169 if (!n_video || video_id < 0)
1170 demuxer->video->id = -2;
1171 else
1172 demuxer->video->id = video_id;
1173 if (!n_audio || audio_id < 0)
1174 demuxer->audio->id = -2;
1175 else
1176 demuxer->audio->id = audio_id;
1177 /* Disable the subs only if there are no text streams at all.
1178 Otherwise the stream to display might be chosen later when the comment
1179 packet is encountered and the user used -slang instead of -sid. */
1180 if (!ogg_d->n_text)
1181 demuxer->sub->id = -2;
1182 else if (text_id >= 0) {
1183 demuxer->sub->id = text_id;
1184 mp_msg(MSGT_DEMUX, MSGL_V,
1185 "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1188 ogg_d->final_granulepos = 0;
1189 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1190 if (!s->end_pos) {
1191 demuxer->seekable = 0;
1192 } else {
1193 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1194 demuxer->movi_end = s->end_pos;
1195 demuxer->seekable = 1;
1196 demux_ogg_scan_stream(demuxer);
1198 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1199 ogg_d->initial_granulepos = 0;
1200 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1202 mp_msg(MSGT_DEMUX, MSGL_V,
1203 "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
1204 n_audio, n_audio > 1 ? "s" : "",
1205 n_video, n_video > 1 ? "s" : "",
1206 ogg_d->n_text, ogg_d->n_text > 1 ? "s" : "");
1208 sh_a = demuxer->audio->sh;
1209 if (sh_a && sh_a->format == FOURCC_VORBIS)
1210 fixup_vorbis_wf(sh_a, ogg_d);
1212 return DEMUXER_TYPE_OGG;
1214 err_out:
1215 return 0;
1218 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds)
1220 ogg_demuxer_t *ogg_d;
1221 stream_t *s;
1222 demux_stream_t *ds;
1223 ogg_sync_state *sync;
1224 ogg_stream_state *os;
1225 ogg_page *page;
1226 ogg_packet pack;
1227 int np = 0, id=0;
1229 s = d->stream;
1230 ogg_d = d->priv;
1231 sync = &ogg_d->sync;
1232 page = &ogg_d->page;
1234 /// Find the stream we are working on
1235 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1236 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n");
1237 return 0;
1240 while (1) {
1241 np = 0;
1242 ds = NULL;
1243 /// Try to get some packet from the current page
1244 while ((np = ogg_stream_packetout(os, &pack)) != 1) {
1245 /// No packet we go the next page
1246 if (np == 0) {
1247 while (1) {
1248 int pa, len;
1249 char *buf;
1251 ogg_d->pos += ogg_d->last_size;
1252 /// Get the next page from the physical stream
1253 while ((pa = ogg_sync_pageseek(sync, page)) <= 0) {
1254 /// Error : we skip some bytes
1255 if (pa < 0) {
1256 mp_msg(MSGT_DEMUX, MSGL_WARN,
1257 "Ogg : Page out not synced, we skip some bytes\n");
1258 ogg_d->pos -= pa;
1259 continue;
1261 /// We need more data
1262 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1263 len = stream_read(s, buf, BLOCK_SIZE);
1264 if (len == 0 && s->eof) {
1265 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n");
1266 return 0;
1268 ogg_sync_wrote(sync, len);
1269 } /// Page loop
1270 ogg_d->last_size = pa;
1271 /// Find the page's logical stream
1272 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1273 mp_msg(MSGT_DEMUX, MSGL_ERR,
1274 "Ogg demuxer error : we met an unknown stream\n");
1275 return 0;
1277 /// Take the page
1278 if (ogg_stream_pagein(os, page) == 0)
1279 break;
1280 /// Page was invalid => retry
1281 mp_msg(MSGT_DEMUX, MSGL_WARN,
1282 "Ogg demuxer : got invalid page !!!!!\n");
1283 ogg_d->pos += ogg_d->last_size;
1285 } else /// Packet was corrupted
1286 mp_msg(MSGT_DEMUX, MSGL_WARN,
1287 "Ogg : bad packet in stream %d\n", id);
1288 } /// Packet loop
1290 /// Is the actual logical stream in use ?
1291 if (id == d->audio->id)
1292 ds = d->audio;
1293 else if (id == d->video->id)
1294 ds = d->video;
1295 else if (ogg_d->subs[id].text)
1296 ds = d->sub;
1298 if (ds) {
1299 if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack))
1300 continue; /// Unuseful packet, get another
1301 d->filepos = ogg_d->pos;
1302 return 1;
1304 } /// while (1)
1307 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1308 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1309 demuxer_t *init_avi_with_ogg(demuxer_t *demuxer)
1311 struct MPOpts *opts = demuxer->opts;
1312 demuxer_t *od;
1313 ogg_demuxer_t *ogg_d;
1314 stream_t *s;
1315 uint32_t hdrsizes[3];
1316 demux_packet_t *dp;
1317 sh_audio_t *sh_audio = demuxer->audio->sh;
1318 int np;
1319 uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
1320 int i;
1321 unsigned char *p = NULL, *buf;
1322 int plen;
1324 /// Check that the cbSize is big enough for the following reads
1325 if (sh_audio->wf->cbSize < 22 + 3 * 4) {
1326 mp_msg(MSGT_DEMUX, MSGL_ERR,
1327 "AVI Ogg : Initial audio header is too small !!!!!\n");
1328 goto fallback;
1330 /// Get the size of the 3 header packet
1331 extradata += 22;
1332 for (i = 0; i < 3; i++) {
1333 hdrsizes[i] = AV_RL32(extradata);
1334 extradata += 4;
1336 // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
1338 /// Check the size
1339 if (sh_audio->wf->cbSize < 22 + 3 * 4 + hdrsizes[0] + hdrsizes[1] + hdrsizes[2]) {
1340 mp_msg(MSGT_DEMUX, MSGL_ERR,
1341 "AVI Ogg : Audio header is too small !!!!!\n");
1342 goto fallback;
1345 // Build the ogg demuxer private datas
1346 ogg_d = calloc(1, sizeof(*ogg_d));
1347 ogg_d->num_sub = 1;
1348 ogg_d->subs = malloc(sizeof(*ogg_d->subs));
1349 ogg_d->subs[0].vorbis = 1;
1351 // Init the ogg physical stream
1352 ogg_sync_init(&ogg_d->sync);
1354 // Get the first page of the stream : we assume there only 1 logical stream
1355 while ((np = ogg_sync_pageout(&ogg_d->sync, &ogg_d->page)) <= 0 ) {
1356 if (np < 0) {
1357 mp_msg(MSGT_DEMUX, MSGL_ERR,
1358 "AVI Ogg error : Can't init using first stream packets\n");
1359 free(ogg_d);
1360 goto fallback;
1362 // Add some data
1363 plen = ds_get_packet(demuxer->audio, &p);
1364 buf = ogg_sync_buffer(&ogg_d->sync, plen);
1365 memcpy(buf, p, plen);
1366 ogg_sync_wrote(&ogg_d->sync, plen);
1368 // Init the logical stream
1369 mp_msg(MSGT_DEMUX, MSGL_DBG2,
1370 "AVI Ogg found page with serial %d\n",
1371 ogg_page_serialno(&ogg_d->page));
1372 ogg_stream_init(&ogg_d->subs[0].stream, ogg_page_serialno(&ogg_d->page));
1373 // Write the page
1374 ogg_stream_pagein(&ogg_d->subs[0].stream, &ogg_d->page);
1376 // Create the ds_stream and the ogg demuxer
1377 s = new_ds_stream(demuxer->audio);
1378 od = new_demuxer(opts, s, DEMUXER_TYPE_OGG, 0, -2, -2, NULL);
1380 /// Add the header packets in the ogg demuxer audio stream
1381 for (i = 0; i < 3; i++) {
1382 dp = new_demux_packet(hdrsizes[i]);
1383 memcpy(dp->buffer, extradata, hdrsizes[i]);
1384 ds_add_packet(od->audio, dp);
1385 extradata += hdrsizes[i];
1388 // Finish setting up the ogg demuxer
1389 od->priv = ogg_d;
1390 sh_audio = new_sh_audio(od, 0);
1391 od->audio->id = 0;
1392 od->video->id = -2;
1393 od->audio->sh = sh_audio;
1394 sh_audio->ds = od->audio;
1395 sh_audio->format = FOURCC_VORBIS;
1396 fixup_vorbis_wf(sh_audio, ogg_d);
1398 /// Return the joined demuxers
1399 return new_demuxers_demuxer(demuxer, od, demuxer);
1401 fallback:
1402 demuxer->audio->id = -2;
1403 return demuxer;
1407 static void demux_ogg_seek(demuxer_t *demuxer, float rel_seek_secs,
1408 float audio_delay, int flags)
1410 ogg_demuxer_t *ogg_d = demuxer->priv;
1411 ogg_sync_state *sync = &ogg_d->sync;
1412 ogg_page* page= &ogg_d->page;
1413 ogg_stream_state *oss;
1414 ogg_stream_t *os;
1415 demux_stream_t *ds;
1416 ogg_packet op;
1417 float rate;
1418 int i, sp, first, precision = 1, do_seek = 1;
1419 vorbis_info *vi = NULL;
1420 int64_t gp = 0, old_gp;
1421 off_t pos, old_pos;
1422 int np;
1423 int is_gp_valid;
1424 float pts;
1425 int is_keyframe;
1426 int samplesize = 1;
1427 ogg_int64_t granulepos_orig;
1429 if (demuxer->video->id >= 0) {
1430 ds = demuxer->video;
1431 rate = ogg_d->subs[ds->id].samplerate;
1432 } else {
1433 ds = demuxer->audio;
1434 os = &ogg_d->subs[ds->id];
1435 vi = &(os->vi);
1436 rate = (float)vi->rate;
1437 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1440 os = &ogg_d->subs[ds->id];
1441 oss = &os->stream;
1443 old_gp = os->lastpos;
1444 old_pos = ogg_d->pos;
1446 //calculate the granulepos to seek to
1447 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1448 if (flags & SEEK_FACTOR) {
1449 if (ogg_d->duration > 0)
1450 gp += ogg_d->duration * rel_seek_secs;
1451 else
1452 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1453 } else
1454 gp += rel_seek_secs * rate;
1455 if (gp < 0)
1456 gp = 0;
1458 //calculate the filepos to seek to
1459 if (ogg_d->syncpoints) {
1460 for (sp = 0; sp < ogg_d->num_syncpoint; sp++)
1461 if (ogg_d->syncpoints[sp].granulepos >= gp)
1462 break;
1464 if (sp >= ogg_d->num_syncpoint)
1465 return;
1466 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp - 1].granulepos)
1467 sp--;
1468 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1469 if (sp > 0 && gp < os->lastpos)
1470 sp--;
1471 if (sp < ogg_d->num_syncpoint - 1 && gp > os->lastpos)
1472 sp++;
1474 pos = ogg_d->syncpoints[sp].page_pos;
1475 precision = 0;
1476 } else {
1477 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1478 if (flags & SEEK_FACTOR)
1479 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1480 else {
1481 if (ogg_d->duration > 0) {
1482 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1483 } else if (os->lastpos > 0) {
1484 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1487 if (pos < 0)
1488 pos = 0;
1489 if (pos > (demuxer->movi_end - demuxer->movi_start))
1490 pos = demuxer->movi_end - demuxer->movi_start;
1491 } // if (ogg_d->syncpoints)
1493 while (1) {
1494 if (do_seek) {
1495 stream_seek(demuxer->stream, pos+demuxer->movi_start);
1496 ogg_sync_reset(sync);
1497 for (i = 0; i < ogg_d->num_sub; i++) {
1498 ogg_stream_reset(&ogg_d->subs[i].stream);
1499 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1501 ogg_d->pos = pos;
1502 ogg_d->last_size = 0;
1503 /* we just guess that we reached correct granulepos, in case a
1504 subsequent search occurs before we read a valid granulepos */
1505 os->lastpos = gp;
1506 first = !(ogg_d->syncpoints);
1507 do_seek=0;
1509 ogg_d->pos += ogg_d->last_size;
1510 ogg_d->last_size = 0;
1511 np = ogg_sync_pageseek(sync, page);
1513 if (np < 0)
1514 ogg_d->pos -= np;
1515 if (np <= 0) { // We need more data
1516 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1517 int len = stream_read(demuxer->stream, buf, BLOCK_SIZE);
1519 if (len == 0 && demuxer->stream->eof) {
1520 mp_msg(MSGT_DEMUX, MSGL_V, "EOF while trying to seek !!!!\n");
1521 return;
1523 ogg_sync_wrote(sync, len);
1524 continue;
1526 ogg_d->last_size = np;
1527 if (ogg_page_serialno(page) != oss->serialno)
1528 continue;
1530 if (ogg_stream_pagein(oss, page) != 0)
1531 continue;
1533 while (1) {
1534 np = ogg_stream_packetout(oss, &op);
1535 if (np < 0)
1536 continue;
1537 else if (np == 0)
1538 break;
1539 if (first) { /* Discard the first packet as it's probably broken,
1540 and we don't have any other means to decide whether it is
1541 complete or not. */
1542 first = 0;
1543 break;
1545 is_gp_valid = (op.granulepos >= 0);
1546 granulepos_orig=op.granulepos;
1547 demux_ogg_read_packet(os, &op, &pts, &is_keyframe, samplesize);
1548 if (precision && is_gp_valid) {
1549 precision--;
1550 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1551 //prepare another seek because we are off by more than 1s
1552 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1553 if (pos < 0)
1554 pos = 0;
1555 if (pos < demuxer->movi_end - demuxer->movi_start) {
1556 do_seek=1;
1557 break;
1561 if (is_gp_valid && pos > 0 && old_gp > gp
1562 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1563 /* prepare another seek because looking for a syncpoint
1564 destroyed the backward search */
1565 pos = old_pos - 1.5 * (old_pos - pos);
1566 if (pos < 0)
1567 pos = 0;
1568 if (pos < demuxer->movi_end - demuxer->movi_start) {
1569 do_seek=1;
1570 break;
1573 if (!precision && (is_keyframe || os->vorbis || os->speex)) {
1574 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1575 vo_sub = &ogg_sub;
1576 vo_osd_changed(OSDTYPE_SUBTITLE);
1578 op.granulepos=granulepos_orig;
1579 demux_ogg_add_packet(ds, os, ds->id, &op);
1580 return;
1585 mp_msg(MSGT_DEMUX, MSGL_ERR, "Can't find the good packet :(\n");
1588 static void demux_close_ogg(demuxer_t *demuxer)
1590 ogg_demuxer_t *ogg_d = demuxer->priv;
1591 ogg_stream_t *os = NULL;
1592 int i;
1594 if (!ogg_d)
1595 return;
1597 #ifdef CONFIG_ICONV
1598 subcp_close();
1599 #endif
1601 ogg_sync_clear(&ogg_d->sync);
1602 if (ogg_d->subs) {
1603 for (i = 0; i < ogg_d->num_sub; i++) {
1604 os = &ogg_d->subs[i];
1605 ogg_stream_clear(&os->stream);
1606 if (os->vi_initialized)
1607 vorbis_info_clear(&os->vi);
1609 free(ogg_d->subs);
1611 if (ogg_d->syncpoints)
1612 free(ogg_d->syncpoints);
1613 if (ogg_d->text_ids)
1614 free(ogg_d->text_ids);
1615 if (ogg_d->text_langs) {
1616 for (i = 0; i < ogg_d->n_text; i++)
1617 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1618 free(ogg_d->text_langs);
1620 free(ogg_d);
1623 static int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg)
1625 ogg_demuxer_t *ogg_d = demuxer->priv;
1626 ogg_stream_t *os;
1627 float rate;
1629 if (demuxer->video->id >= 0) {
1630 os = &ogg_d->subs[demuxer->video->id];
1631 rate = os->samplerate;
1632 } else {
1633 os = &ogg_d->subs[demuxer->audio->id];
1634 rate = os->vi.rate;
1637 switch(cmd) {
1638 case DEMUXER_CTRL_GET_TIME_LENGTH:
1639 if (ogg_d->duration <= 0)
1640 return DEMUXER_CTRL_DONTKNOW;
1641 *(double *)arg = (double)(ogg_d->duration) / rate;
1642 return DEMUXER_CTRL_GUESS;
1644 case DEMUXER_CTRL_GET_PERCENT_POS:
1645 if (ogg_d->duration <= 0)
1646 return DEMUXER_CTRL_DONTKNOW;
1647 *(int *)arg = ((os->lastpos - ogg_d->initial_granulepos) * 100) / ogg_d->duration;
1648 return DEMUXER_CTRL_OK;
1650 default:
1651 return DEMUXER_CTRL_NOTIMPL;
1655 const demuxer_desc_t demuxer_desc_ogg = {
1656 "Ogg demuxer",
1657 "ogg",
1658 "Ogg",
1659 "?",
1661 DEMUXER_TYPE_OGG,
1662 1, // safe autodetect
1663 demux_ogg_open,
1664 demux_ogg_fill_buffer,
1665 NULL,
1666 demux_close_ogg,
1667 demux_ogg_seek,
1668 demux_ogg_control