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