Extend -vf format to allow substituting the format for a compatible one
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blob58876c65225eeeb3d7ad050bfc84dacfd90da59f
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 "mp_msg.h"
29 #include "help_mp.h"
30 #include "stream/stream.h"
31 #include "demuxer.h"
32 #include "stheader.h"
33 #include "libavutil/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;
167 extern int dvdsub_id;
169 //-------- subtitle support - should be moved to decoder layer, and queue
170 // - subtitles up in demuxer buffer...
172 #include "subreader.h"
173 #include "libvo/sub.h"
174 #define OGG_SUB_MAX_LINE 128
176 static subtitle ogg_sub;
177 //FILE* subout;
179 static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
181 int lcv;
182 char *packet = pack->packet;
184 if (pack->bytes < 4)
185 return;
186 mp_msg(MSGT_DEMUX, MSGL_DBG2, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
187 (unsigned char)packet[0],
188 (unsigned char)packet[1],
189 (unsigned char)packet[2],
190 &packet[3]);
192 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
193 // Find data start
194 double endpts = MP_NOPTS_VALUE;
195 int32_t duration = 0;
196 int16_t hdrlen = (*packet & PACKET_LEN_BITS01) >> 6, i;
198 hdrlen |= (*packet & PACKET_LEN_BITS2) << 1;
199 lcv = 1 + hdrlen;
200 if (pack->bytes < lcv)
201 return;
202 for (i = hdrlen; i > 0; i--) {
203 duration <<= 8;
204 duration |= (unsigned char)packet[i];
206 if (hdrlen > 0 && duration > 0) {
207 float pts;
209 if (pack->granulepos == -1)
210 pack->granulepos = os->lastpos + os->lastsize;
211 pts = (float)pack->granulepos / (float)os->samplerate;
212 endpts = 1.0 + pts + (float)duration / 1000.0;
214 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
215 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
218 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg sub lines: %d first: '%s'\n",
219 ogg_sub.lines, ogg_sub.text[0]);
220 #ifdef CONFIG_ICONV
221 subcp_recode(&ogg_sub);
222 #endif
223 vo_sub = &ogg_sub;
224 vo_osd_changed(OSDTYPE_SUBTITLE);
228 // get the logical stream of the current page
229 // fill os if non NULL and return the stream id
230 static int demux_ogg_get_page_stream(ogg_demuxer_t *ogg_d,
231 ogg_stream_state **os)
233 int id, s_no;
234 ogg_page *page = &ogg_d->page;
236 s_no = ogg_page_serialno(page);
238 for (id = 0; id < ogg_d->num_sub; id++)
239 if (s_no == ogg_d->subs[id].stream.serialno)
240 break;
242 if (id == ogg_d->num_sub) {
243 // If we have only one vorbis stream allow the stream id to change
244 // it's normal on radio stream (each song have an different id).
245 // But we (or the codec?) should check that the samplerate, etc
246 // doesn't change (for radio stream it's ok)
247 if (ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
248 ogg_stream_reset(&ogg_d->subs[0].stream);
249 ogg_stream_init(&ogg_d->subs[0].stream, s_no);
250 id = 0;
251 } else
252 return -1;
255 if (os)
256 *os = &ogg_d->subs[id].stream;
258 return id;
261 static unsigned char *demux_ogg_read_packet(ogg_stream_t *os, ogg_packet *pack,
262 float *pts, int *flags,
263 int samplesize)
265 unsigned char *data = pack->packet;
266 int size = pack->bytes;
268 *pts = MP_NOPTS_VALUE;
269 *flags = 0;
271 if (os->vorbis) {
272 if (*pack->packet & PACKET_TYPE_HEADER) {
273 os->hdr_packets++;
274 } else {
275 vorbis_info *vi;
276 int32_t blocksize = 0;
278 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
279 vi = os->vi_initialized ? &os->vi : NULL;
280 if (vi)
281 blocksize = vorbis_packet_blocksize(vi, pack) / samplesize;
282 // Calculate the timestamp if the packet don't have any
283 if (pack->granulepos == -1) {
284 pack->granulepos = os->lastpos;
285 if (os->lastsize > 0)
286 pack->granulepos += os->lastsize;
287 } else
288 *flags = 1;
289 if (vi)
290 *pts = pack->granulepos / (float)vi->rate;
291 os->lastsize = blocksize;
292 os->lastpos = pack->granulepos;
294 } else if (os->speex) {
295 // whole packet (default)
296 # ifdef CONFIG_OGGTHEORA
297 } else if (os->theora) {
298 /* we pass complete packets to theora, mustn't strip the header! */
299 os->lastsize = 1;
301 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
302 have theora_state st, until all header packets were passed to the
303 decoder. */
304 if (!size || !(*data&0x80)) {
305 int keyframe_granule_shift = _ilog(os->keyframe_frequency_force - 1);
306 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
308 if (pack->granulepos >= 0) {
309 os->lastpos = pack->granulepos >> keyframe_granule_shift;
310 os->lastpos += pack->granulepos & iframemask;
311 *flags = (pack->granulepos & iframemask) == 0;
312 } else {
313 os->lastpos++;
315 pack->granulepos = os->lastpos;
316 *pts = (double)os->lastpos / (double)os->samplerate;
318 #endif /* CONFIG_OGGTHEORA */
319 } else if (os->flac) {
320 /* we pass complete packets to flac, mustn't strip the header! */
321 if (os->flac == 2 && pack->packet[0] != 0xff)
322 return NULL;
323 } else {
324 if (*pack->packet & PACKET_TYPE_HEADER) {
325 os->hdr_packets++;
326 } else {
327 // Find data start
328 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01) >> 6;
330 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) << 1;
331 data = pack->packet + 1 + hdrlen;
332 // Calculate the timestamp
333 if (pack->granulepos == -1)
334 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
335 // If we already have a timestamp it can be a syncpoint
336 if (*pack->packet & PACKET_IS_SYNCPOINT)
337 *flags = 1;
338 *pts = pack->granulepos / os->samplerate;
339 // Save the packet length and timestamp
340 os->lastsize = 0;
341 while (hdrlen) {
342 os->lastsize <<= 8;
343 os->lastsize |= pack->packet[hdrlen];
344 hdrlen--;
346 os->lastpos = pack->granulepos;
349 return data;
352 // check if clang has substring from comma separated langlist
353 static int demux_ogg_check_lang(const char *clang, const char *langlist)
355 const char *c;
357 if (!langlist || !*langlist)
358 return 0;
359 while ((c = strchr(langlist, ','))) {
360 if (!strncasecmp(clang, langlist, c - langlist))
361 return 1;
362 langlist = &c[1];
364 if (!strncasecmp(clang, langlist, strlen(langlist)))
365 return 1;
366 return 0;
369 /** \brief Change the current subtitle stream and return its ID.
371 \param demuxer The demuxer whose subtitle stream will be changed.
372 \param new_num The number of the new subtitle track. The number must be
373 between 0 and ogg_d->n_text - 1.
375 \returns The Ogg stream number ( = page serial number) of the newly selected
376 track.
378 static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
380 ogg_demuxer_t *ogg_d = demuxer->priv;
381 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
384 /** \brief Translate the ogg track number into the subtitle number.
385 * \param demuxer The demuxer about whose subtitles we are inquiring.
386 * \param id The ogg track number of the subtitle track.
388 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id)
390 ogg_demuxer_t *ogg_d = demuxer->priv;
391 int i;
393 for (i = 0; i < ogg_d->n_text; i++)
394 if (ogg_d->text_ids[i] == id)
395 return i;
396 return -1;
399 /// Try to print out comments and also check for LANGUAGE= tag
400 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os,
401 int id, vorbis_comment *vc)
403 const char *hdr, *val;
404 char **cmt = vc->user_comments;
405 int index, i;
406 ogg_demuxer_t *ogg_d = d->priv;
407 static const struct table {
408 const char *ogg;
409 const char *mp;
410 } table[] = {
411 { "ENCODED_USING", "Software" },
412 { "ENCODER_URL", "Encoder URL" },
413 { "TITLE", "Title" },
414 { "ARTIST", "Artist" },
415 { "COMMENT", "Comments" },
416 { "DATE", "Creation Date" },
417 { "GENRE", "Genre" },
418 { "ALBUM", "Album" },
419 { "TRACKNUMBER", "Track" },
420 { NULL, NULL },
423 while (*cmt) {
424 hdr = NULL;
425 if (!strncasecmp(*cmt, "LANGUAGE=", 9)) {
426 val = *cmt + 9;
427 if (ogg_d->subs[id].text)
428 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n",
429 ogg_d->subs[id].id, val);
430 else if (id != d->video->id)
431 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n",
432 ogg_d->subs[id].id, val);
433 if (ogg_d->subs[id].text)
434 mp_msg(MSGT_DEMUX, MSGL_INFO,
435 "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
436 ogg_d->subs[id].id, val);
437 // copy this language name into the array
438 index = demux_ogg_sub_reverse_id(d, id);
439 if (index >= 0) {
440 sh_sub_t *sh;
442 // in case of malicious files with more than one lang per track:
443 if (ogg_d->text_langs[index])
444 free(ogg_d->text_langs[index]);
445 ogg_d->text_langs[index] = strdup(val);
446 sh = d->s_streams[index];
447 if (sh && sh->lang)
448 free(sh->lang);
449 if (sh)
450 sh->lang = strdup(val);
452 // check for -slang if subs are uninitialized yet
453 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang)) {
454 d->sub->id = index;
455 dvdsub_id = index;
456 mp_msg(MSGT_DEMUX, MSGL_V,
457 "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
458 id, val);
460 else
461 hdr = "Language";
463 else {
464 for (i = 0; table[i].ogg; i++) {
465 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
466 (*cmt)[strlen(table[i].ogg)] == '=') {
467 hdr = table[i].mp;
468 val = *cmt + strlen(table[i].ogg) + 1;
472 if (hdr)
473 demux_info_add(d, hdr, val);
474 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
475 cmt++;
479 /// Calculate the timestamp and add the packet to the demux stream
480 // return 1 if the packet was added, 0 otherwise
481 static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
482 int id, ogg_packet *pack)
484 demuxer_t *d = ds->demuxer;
485 demux_packet_t *dp;
486 unsigned char *data;
487 float pts = 0;
488 int flags = 0;
489 int samplesize = 1;
491 // If packet is an comment header then we try to get comments at first
492 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
493 vorbis_info vi;
494 vorbis_comment vc;
496 vorbis_info_init(&vi);
497 vorbis_comment_init(&vc);
498 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
499 if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
500 demux_ogg_check_comments(d, os, id, &vc);
501 vorbis_comment_clear(&vc);
502 vorbis_info_clear(&vi);
504 if (os->text) {
505 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
506 demux_ogg_add_sub(os, pack);
507 return 0;
509 if (os->speex) {
510 // discard first two packets, they contain the header and comment
511 if (os->hdr_packets < 2) {
512 os->hdr_packets++;
513 return 0;
515 } else {
516 // If packet is an header we jump it except for vorbis and theora
517 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
518 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
519 // handled differently for each and every stream type. The joy! The joy!
520 if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
521 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
522 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
523 return 0;
526 // For vorbis packet the packet is the data, for other codec we must jump
527 // the header
528 if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
529 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
531 data = demux_ogg_read_packet(os, pack, &pts, &flags, samplesize);
532 if (!data)
533 return 0;
535 /// Clear subtitles if necessary (for broken files)
536 if (sub_clear_text(&ogg_sub, pts)) {
537 vo_sub = &ogg_sub;
538 vo_osd_changed(OSDTYPE_SUBTITLE);
540 /// Send the packet
541 dp = new_demux_packet(pack->bytes - (data - pack->packet));
542 memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
543 dp->pts = pts;
544 dp->flags = flags;
545 ds_add_packet(ds, dp);
546 mp_msg(MSGT_DEMUX, MSGL_DBG2,
547 "New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
548 dp, ds, pts, dp->len, flags);
549 return 1;
552 /// if -forceidx build a table of all syncpoints to make seeking easier
553 /// otherwise try to get at least the final_granulepos
554 static void demux_ogg_scan_stream(demuxer_t *demuxer)
556 ogg_demuxer_t *ogg_d = demuxer->priv;
557 stream_t *s = demuxer->stream;
558 ogg_sync_state *sync = &ogg_d->sync;
559 ogg_page *page = &ogg_d->page;
560 ogg_stream_state *oss;
561 ogg_stream_t *os;
562 ogg_packet op;
563 int np, sid, p, samplesize = 1;
564 off_t pos, last_pos;
566 pos = last_pos = demuxer->movi_start;
568 // Reset the stream
569 stream_seek(s, demuxer->movi_start);
570 ogg_sync_reset(sync);
572 // Get the serial number of the stream we use
573 if (demuxer->video->id >= 0) {
574 sid = demuxer->video->id;
575 } else if (demuxer->audio->id >= 0) {
576 sid = demuxer->audio->id;
577 if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
578 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
579 } else
580 return;
581 os = &ogg_d->subs[sid];
582 oss = &os->stream;
584 while (1) {
585 np = ogg_sync_pageseek(sync, page);
586 if (np < 0) { // We had to skip some bytes
587 if (index_mode == 2)
588 mp_msg(MSGT_DEMUX, MSGL_ERR,
589 "Bad page sync while building syncpoints table (%d)\n",
590 -np);
591 pos += -np;
592 continue;
594 if (np <= 0) { // We need more data
595 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
596 int len = stream_read(s, buf, BLOCK_SIZE);
598 if (len == 0 && s->eof)
599 break;
600 ogg_sync_wrote(sync, len);
601 continue;
603 // The page is ready
604 //ogg_sync_pageout(sync, page);
605 if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
606 pos += np;
607 continue;
609 if (ogg_stream_pagein(oss, page) != 0) {
610 mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
611 pos += np;
612 continue;
614 p = 0;
615 while (ogg_stream_packetout(oss, &op) == 1) {
616 float pts;
617 int flags;
619 demux_ogg_read_packet(os, &op, &pts, &flags, samplesize);
620 if (op.granulepos >= 0) {
621 ogg_d->final_granulepos = op.granulepos;
622 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
623 ogg_d->initial_granulepos = op.granulepos;
624 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
625 //the 270000 are just a wild guess
626 stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
627 ogg_sync_reset(sync);
628 continue;
632 if (index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
633 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1)
634 break;
635 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t));
636 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
637 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
638 ogg_d->num_syncpoint++;
640 p++;
642 if (p > 1 || (p == 1 && !ogg_page_continued(page)))
643 last_pos = pos;
644 pos += np;
645 if (index_mode == 2)
646 mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r",
647 (int)(pos * 100 / s->end_pos));
650 if (index_mode == 2) {
651 mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
652 mp_msg(MSGT_DEMUX, MSGL_V,
653 "Ogg syncpoints table builed: %d syncpoints\n",
654 ogg_d->num_syncpoint);
657 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n",
658 ogg_d->final_granulepos);
660 stream_reset(s);
661 stream_seek(s, demuxer->movi_start);
662 ogg_sync_reset(sync);
663 for (np = 0; np < ogg_d->num_sub; np++) {
664 ogg_stream_reset(&ogg_d->subs[np].stream);
665 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
668 // Get the first page
669 while (1) {
670 np = ogg_sync_pageout(sync, page);
671 if (np <= 0) { // We need more data
672 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
673 int len = stream_read(s, buf, BLOCK_SIZE);
675 if (len == 0 && s->eof) {
676 mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n");
677 break;
679 ogg_sync_wrote(sync, len);
680 continue;
682 demux_ogg_get_page_stream(ogg_d, &oss);
683 ogg_stream_pagein(oss, page);
684 break;
688 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
690 int i, offset;
691 int ris, init_error = 0;
692 ogg_packet op[3];
693 unsigned char *buf[3];
694 unsigned char *ptr;
695 unsigned int len;
696 ogg_stream_t *os = &od->subs[sh->ds->id];
697 vorbis_comment vc;
699 vorbis_info_init(&os->vi);
700 vorbis_comment_init(&vc);
701 for (i = 0; i < 3; i++) {
702 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
703 mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
704 if (op[i].bytes < 0) {
705 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
706 return;
708 buf[i] = malloc(op[i].bytes);
709 if (!buf[i])
710 return;
711 memcpy(buf[i], op[i].packet, op[i].bytes);
713 op[i].b_o_s = (i == 0);
714 ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]);
715 if (ris < 0) {
716 init_error = 1;
717 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
720 vorbis_comment_clear(&vc);
721 if (!init_error)
722 os->vi_initialized = 1;
724 len = op[0].bytes + op[1].bytes + op[2].bytes;
725 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len / 255 + 64);
726 ptr = (unsigned char*)(sh->wf + 1);
728 ptr[0] = 2;
729 offset = 1;
730 offset += store_ughvlc(&ptr[offset], op[0].bytes);
731 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset);
732 offset += store_ughvlc(&ptr[offset], op[1].bytes);
733 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset);
734 for (i = 0; i < 3; i++) {
735 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
736 memcpy(&ptr[offset], buf[i], op[i].bytes);
737 offset += op[i].bytes;
739 sh->wf->cbSize = offset;
740 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
741 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
743 if (op[0].bytes >= 29) {
744 unsigned int br;
745 int nombr, minbr, maxbr;
747 ptr = buf[0];
748 sh->channels = ptr[11];
749 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
750 maxbr = AV_RL32(&ptr[16]); //max
751 nombr = AV_RL32(&ptr[20]); //nominal
752 minbr = AV_RL32(&ptr[24]); //minimum
754 if (maxbr == -1)
755 maxbr = 0;
756 if (nombr == -1)
757 nombr = 0;
758 if (minbr == -1)
759 minbr = 0;
761 br = maxbr / 8;
762 if (!br)
763 br = nombr / 8;
764 if (!br)
765 br = minbr / 8;
766 sh->wf->nAvgBytesPerSec = br;
767 sh->wf->wBitsPerSample = 16;
768 sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8;
770 mp_msg(MSGT_DEMUX, MSGL_V,
771 "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
772 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec,
773 maxbr, nombr, minbr);
775 free(buf[2]);
776 free(buf[1]);
777 free(buf[0]);
780 /// Open an ogg physical stream
781 // Not static because it's used also in demuxer_avi.c
782 int demux_ogg_open(demuxer_t *demuxer)
784 ogg_demuxer_t *ogg_d;
785 stream_t *s;
786 char *buf;
787 int np, s_no, n_audio = 0, n_video = 0;
788 int audio_id = -1, video_id = -1, text_id = -1;
789 ogg_sync_state *sync;
790 ogg_page *page;
791 ogg_packet pack;
792 sh_audio_t *sh_a;
793 sh_video_t *sh_v;
795 #ifdef CONFIG_ICONV
796 subcp_open(NULL);
797 #endif
799 s = demuxer->stream;
801 demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d));
802 sync = &ogg_d->sync;
803 page = &ogg_d->page;
805 ogg_sync_init(sync);
807 while (1) {
808 /// Try to get a page
809 ogg_d->pos += ogg_d->last_size;
810 np = ogg_sync_pageseek(sync, page);
811 /// Error
812 if (np < 0) {
813 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n");
814 goto err_out;
816 /// Need some more data
817 if (np == 0) {
818 int len;
820 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
821 len = stream_read(s, buf, BLOCK_SIZE);
822 if (len == 0 && s->eof) {
823 goto err_out;
825 ogg_sync_wrote(sync, len);
826 continue;
828 ogg_d->last_size = np;
829 // We got one page now
831 if (!ogg_page_bos(page)) { // It's not a beginning page
832 // Header parsing end here, we need to get the page otherwise it will be lost
833 int id = demux_ogg_get_page_stream(ogg_d, NULL);
834 if (id >= 0)
835 ogg_stream_pagein(&ogg_d->subs[id].stream, page);
836 else
837 mp_msg(MSGT_DEMUX, MSGL_ERR,
838 "Ogg : Warning found none bos page from unknown stream %d\n",
839 ogg_page_serialno(page));
840 break;
843 /// Init the data structure needed for a logical stream
844 ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1,
845 sizeof(ogg_stream_t));
846 memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t));
847 /// Get the stream serial number
848 s_no = ogg_page_serialno(page);
849 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no);
850 mp_msg(MSGT_DEMUX, MSGL_DBG2,
851 "Ogg : Found a stream with serial=%d\n", s_no);
852 // Take the first page
853 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page);
854 // Get first packet of the page
855 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack);
857 // Reset our vars
858 sh_a = NULL;
859 sh_v = NULL;
861 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
863 // Check for Vorbis
864 if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) {
865 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
866 sh_a->format = FOURCC_VORBIS;
867 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
868 ogg_d->subs[ogg_d->num_sub].id = n_audio;
869 n_audio++;
870 mp_msg(MSGT_DEMUX, MSGL_INFO,
871 "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
872 ogg_d->num_sub, n_audio - 1);
873 } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) {
874 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
875 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
876 sh_a->format = FOURCC_SPEEX;
877 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
878 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
879 sh_a->wf->wFormatTag = sh_a->format;
880 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
881 sh_a->wf->nBlockAlign = 0;
882 sh_a->wf->wBitsPerSample = 16;
883 sh_a->samplesize = 2;
884 sh_a->wf->cbSize = pack.bytes;
885 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
887 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
888 ogg_d->subs[ogg_d->num_sub].speex = 1;
889 ogg_d->subs[ogg_d->num_sub].id = n_audio;
890 n_audio++;
891 mp_msg(MSGT_DEMUX, MSGL_INFO,
892 "[Ogg] stream %d: audio (Speex), -aid %d\n",
893 ogg_d->num_sub, n_audio - 1);
895 // check for Theora
896 #ifdef CONFIG_OGGTHEORA
897 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
898 int errorCode = 0;
899 theora_info inf;
900 theora_comment cc;
902 theora_info_init (&inf);
903 theora_comment_init (&cc);
905 errorCode = theora_decode_header (&inf, &cc, &pack);
906 if (errorCode) {
907 mp_msg(MSGT_DEMUX, MSGL_ERR,
908 "Theora header parsing failed: %i \n", errorCode);
909 } else {
910 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
912 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
913 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
914 sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA;
915 sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator;
916 sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator;
917 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
918 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
919 sh_v->bih->biBitCount = 24;
920 sh_v->bih->biPlanes = 3;
921 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight);
922 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
923 ogg_d->subs[ogg_d->num_sub].theora = 1;
924 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
925 ogg_d->subs[ogg_d->num_sub].id = n_video;
926 n_video++;
927 mp_msg(MSGT_DEMUX, MSGL_INFO,
928 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
929 ogg_d->num_sub,
930 (int)inf.version_major,
931 (int)inf.version_minor,
932 (int)inf.version_subminor,
933 n_video - 1);
934 if (mp_msg_test(MSGT_HEADER, MSGL_V))
935 print_video_header(sh_v->bih, MSGL_V);
937 theora_comment_clear(&cc);
938 theora_info_clear(&inf);
939 #endif /* CONFIG_OGGTHEORA */
940 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
941 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
942 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
943 ogg_d->subs[ogg_d->num_sub].id = n_audio;
944 n_audio++;
945 ogg_d->subs[ogg_d->num_sub].flac = 1;
946 sh_a->wf = NULL;
947 mp_msg(MSGT_DEMUX, MSGL_INFO,
948 "[Ogg] stream %d: audio (FLAC), -aid %d\n",
949 ogg_d->num_sub, n_audio - 1);
950 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
951 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
952 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
953 ogg_d->subs[ogg_d->num_sub].id = n_audio;
954 n_audio++;
955 ogg_d->subs[ogg_d->num_sub].flac = 2;
956 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
957 sh_a->wf->wFormatTag = sh_a->format;
958 sh_a->wf->cbSize = 34;
959 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
960 mp_msg(MSGT_DEMUX, MSGL_INFO,
961 "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
962 ogg_d->num_sub, n_audio - 1);
964 /// Check for old header
965 } else if (pack.bytes >= 142 &&
966 !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) {
968 // Old video header
969 if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) {
970 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
971 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
972 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
973 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69],
974 pack.packet[70], pack.packet[71]);
975 sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001;
976 sh_v->fps = 1 / sh_v->frametime;
977 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176);
978 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180);
979 sh_v->bih->biBitCount = AV_RL16(pack.packet + 182);
980 if (!sh_v->bih->biBitCount)
981 sh_v->bih->biBitCount = 24; // hack, FIXME
982 sh_v->bih->biPlanes = 1;
983 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
985 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
986 ogg_d->subs[ogg_d->num_sub].id = n_video;
987 n_video++;
988 mp_msg(MSGT_DEMUX, MSGL_INFO,
989 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
990 ogg_d->num_sub, pack.packet[68], pack.packet[69],
991 pack.packet[70], pack.packet[71], n_video - 1);
992 if (mp_msg_test(MSGT_HEADER, MSGL_V))
993 print_video_header(sh_v->bih, MSGL_V);
994 // Old audio header
995 } else if (AV_RL32(pack.packet + 96) == 0x05589F81) {
996 unsigned int extra_size;
998 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
999 extra_size = AV_RL16(pack.packet + 140);
1000 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
1001 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124);
1002 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126);
1003 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128);
1004 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132);
1005 sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136);
1006 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138);
1007 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1008 sh_a->wf->cbSize = extra_size;
1009 if (extra_size > 0)
1010 memcpy(((char *)sh_a->wf) + sizeof(WAVEFORMATEX),
1011 pack.packet + 142, extra_size);
1013 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1014 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1015 n_audio++;
1016 mp_msg(MSGT_DEMUX, MSGL_INFO,
1017 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1018 ogg_d->num_sub, sh_a->format, n_audio - 1);
1019 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1020 print_wave_header(sh_a->wf, MSGL_V);
1021 } else
1022 mp_msg(MSGT_DEMUX, MSGL_WARN,
1023 "Ogg stream %d contains an old header but the header type is unknown\n",
1024 ogg_d->num_sub);
1026 // Check new header
1027 } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
1028 pack.bytes >= (int)sizeof(stream_header) + 1) {
1029 stream_header *st = (stream_header*)(pack.packet + 1);
1030 /// New video header
1031 if (strncmp(st->streamtype, "video", 5) == 0) {
1032 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
1033 sh_v->bih = calloc(1, sizeof(BITMAPINFOHEADER));
1034 sh_v->bih->biSize = sizeof(BITMAPINFOHEADER);
1035 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1],
1036 st->subtype[2], st->subtype[3]);
1037 sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001;
1038 sh_v->fps = 1.0 / sh_v->frametime;
1039 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
1040 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1041 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1042 if (!sh_v->bih->biBitCount)
1043 sh_v->bih->biBitCount = 24; // hack, FIXME
1044 sh_v->bih->biPlanes = 1;
1045 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
1047 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
1048 ogg_d->subs[ogg_d->num_sub].id = n_video;
1049 n_video++;
1050 mp_msg(MSGT_DEMUX, MSGL_INFO,
1051 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1052 ogg_d->num_sub, st->subtype[0], st->subtype[1],
1053 st->subtype[2], st->subtype[3], n_video - 1);
1054 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1055 print_video_header(sh_v->bih, MSGL_V);
1056 /// New audio header
1057 } else if (strncmp(st->streamtype, "audio", 5) == 0) {
1058 char buffer[5];
1059 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1060 unsigned int extra_offset = 0;
1062 memcpy(buffer, st->subtype, 4);
1063 buffer[4] = '\0';
1065 /* Nasty workaround. stream_header.size seems not to contain the real
1066 size in all cases. There are four extra bytes that are unaccounted
1067 for in front of the real codec initialization data _at least_ for
1068 AAC. So far I've only seen those bytes being all 0, so we can
1069 just skip them here. */
1070 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1071 extra_size -= 4;
1072 extra_offset = 4;
1075 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
1076 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + extra_size);
1077 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1078 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1079 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1080 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1081 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1082 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1083 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1084 sh_a->wf->cbSize = extra_size;
1085 if (extra_size)
1086 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),
1087 ((char *)(st+1))+extra_offset, extra_size);
1089 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1090 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1091 n_audio++;
1092 mp_msg(MSGT_DEMUX, MSGL_INFO,
1093 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1094 ogg_d->num_sub, sh_a->format, n_audio - 1);
1095 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1096 print_wave_header(sh_a->wf, MSGL_V);
1098 /// Check for text (subtitles) header
1099 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1100 mp_msg(MSGT_DEMUX, MSGL_INFO,
1101 "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
1102 ogg_d->num_sub, ogg_d->n_text);
1103 ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10;
1104 ogg_d->subs[ogg_d->num_sub].text = 1;
1105 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1106 if (demuxer->sub->id == ogg_d->n_text)
1107 text_id = ogg_d->num_sub;
1108 new_sh_sub(demuxer, ogg_d->n_text);
1109 ogg_d->n_text++;
1110 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids));
1111 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1112 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs));
1113 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1114 //// Unknown header type
1115 } else
1116 mp_msg(MSGT_DEMUX, MSGL_ERR,
1117 "Ogg stream %d has a header marker but is of an unknown type\n",
1118 ogg_d->num_sub);
1119 /// Unknown (invalid ?) header
1120 } else
1121 mp_msg(MSGT_DEMUX, MSGL_ERR,
1122 "Ogg stream %d is of an unknown type\n",
1123 ogg_d->num_sub);
1125 if (sh_a || sh_v) {
1126 demux_stream_t *ds = NULL;
1127 if (sh_a) {
1128 // If the audio stream is not defined we took the first one
1129 if (demuxer->audio->id == -1) {
1130 demuxer->audio->id = n_audio - 1;
1131 //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
1133 /// Is it the stream we want
1134 if (demuxer->audio->id == n_audio - 1) {
1135 demuxer->audio->sh = sh_a;
1136 sh_a->ds = demuxer->audio;
1137 ds = demuxer->audio;
1138 audio_id = ogg_d->num_sub;
1141 if (sh_v) {
1142 /// Also for video
1143 if (demuxer->video->id == -1) {
1144 demuxer->video->id = n_video - 1;
1145 //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
1147 if (demuxer->video->id == n_video - 1) {
1148 demuxer->video->sh = sh_v;
1149 sh_v->ds = demuxer->video;
1150 ds = demuxer->video;
1151 video_id = ogg_d->num_sub;
1154 /// Add the header packets if the stream isn't seekable
1155 if (ds && !s->end_pos) {
1156 /// Finish the page, otherwise packets will be lost
1157 do {
1158 demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub],
1159 ogg_d->num_sub, &pack);
1160 } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1);
1163 ogg_d->num_sub++;
1166 if (!n_video && !n_audio) {
1167 goto err_out;
1170 if (!n_video || video_id < 0)
1171 demuxer->video->id = -2;
1172 else
1173 demuxer->video->id = video_id;
1174 if (!n_audio || audio_id < 0)
1175 demuxer->audio->id = -2;
1176 else
1177 demuxer->audio->id = audio_id;
1178 /* Disable the subs only if there are no text streams at all.
1179 Otherwise the stream to display might be chosen later when the comment
1180 packet is encountered and the user used -slang instead of -sid. */
1181 if (!ogg_d->n_text)
1182 demuxer->sub->id = -2;
1183 else if (text_id >= 0) {
1184 demuxer->sub->id = text_id;
1185 mp_msg(MSGT_DEMUX, MSGL_V,
1186 "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1189 ogg_d->final_granulepos = 0;
1190 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1191 if (!s->end_pos) {
1192 demuxer->seekable = 0;
1193 } else {
1194 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1195 demuxer->movi_end = s->end_pos;
1196 demuxer->seekable = 1;
1197 demux_ogg_scan_stream(demuxer);
1199 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1200 ogg_d->initial_granulepos = 0;
1201 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1203 mp_msg(MSGT_DEMUX, MSGL_V,
1204 "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
1205 n_audio, n_audio > 1 ? "s" : "",
1206 n_video, n_video > 1 ? "s" : "",
1207 ogg_d->n_text, ogg_d->n_text > 1 ? "s" : "");
1209 sh_a = demuxer->audio->sh;
1210 if (sh_a && sh_a->format == FOURCC_VORBIS)
1211 fixup_vorbis_wf(sh_a, ogg_d);
1213 return DEMUXER_TYPE_OGG;
1215 err_out:
1216 return 0;
1219 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds)
1221 ogg_demuxer_t *ogg_d;
1222 stream_t *s;
1223 demux_stream_t *ds;
1224 ogg_sync_state *sync;
1225 ogg_stream_state *os;
1226 ogg_page *page;
1227 ogg_packet pack;
1228 int np = 0, id=0;
1230 s = d->stream;
1231 ogg_d = d->priv;
1232 sync = &ogg_d->sync;
1233 page = &ogg_d->page;
1235 /// Find the stream we are working on
1236 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1237 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n");
1238 return 0;
1241 while (1) {
1242 np = 0;
1243 ds = NULL;
1244 /// Try to get some packet from the current page
1245 while ((np = ogg_stream_packetout(os, &pack)) != 1) {
1246 /// No packet we go the next page
1247 if (np == 0) {
1248 while (1) {
1249 int pa, len;
1250 char *buf;
1252 ogg_d->pos += ogg_d->last_size;
1253 /// Get the next page from the physical stream
1254 while ((pa = ogg_sync_pageseek(sync, page)) <= 0) {
1255 /// Error : we skip some bytes
1256 if (pa < 0) {
1257 mp_msg(MSGT_DEMUX, MSGL_WARN,
1258 "Ogg : Page out not synced, we skip some bytes\n");
1259 ogg_d->pos -= pa;
1260 continue;
1262 /// We need more data
1263 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1264 len = stream_read(s, buf, BLOCK_SIZE);
1265 if (len == 0 && s->eof) {
1266 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n");
1267 return 0;
1269 ogg_sync_wrote(sync, len);
1270 } /// Page loop
1271 ogg_d->last_size = pa;
1272 /// Find the page's logical stream
1273 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1274 mp_msg(MSGT_DEMUX, MSGL_ERR,
1275 "Ogg demuxer error : we met an unknown stream\n");
1276 return 0;
1278 /// Take the page
1279 if (ogg_stream_pagein(os, page) == 0)
1280 break;
1281 /// Page was invalid => retry
1282 mp_msg(MSGT_DEMUX, MSGL_WARN,
1283 "Ogg demuxer : got invalid page !!!!!\n");
1284 ogg_d->pos += ogg_d->last_size;
1286 } else /// Packet was corrupted
1287 mp_msg(MSGT_DEMUX, MSGL_WARN,
1288 "Ogg : bad packet in stream %d\n", id);
1289 } /// Packet loop
1291 /// Is the actual logical stream in use ?
1292 if (id == d->audio->id)
1293 ds = d->audio;
1294 else if (id == d->video->id)
1295 ds = d->video;
1296 else if (ogg_d->subs[id].text)
1297 ds = d->sub;
1299 if (ds) {
1300 if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack))
1301 continue; /// Unuseful packet, get another
1302 d->filepos = ogg_d->pos;
1303 return 1;
1305 } /// while (1)
1308 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1309 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1310 demuxer_t *init_avi_with_ogg(demuxer_t *demuxer)
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(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