vesa_lvo.c: make functions static
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blobfe6bd27601a9031df7e545a158dacf4174ee7c7b
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 if (ogg_d->text_langs[index])
440 free(ogg_d->text_langs[index]);
441 ogg_d->text_langs[index] = strdup(val);
442 sh = d->s_streams[index];
443 if (sh && sh->lang)
444 free(sh->lang);
445 if (sh)
446 sh->lang = strdup(val);
448 // check for -slang if subs are uninitialized yet
449 if (os->text && d->sub->id < 0
450 && demux_ogg_check_lang(val, d->opts->sub_lang)) {
451 d->sub->id = index;
452 d->opts->sub_id = index;
453 mp_msg(MSGT_DEMUX, MSGL_V,
454 "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
455 id, val);
457 else
458 hdr = "Language";
460 else {
461 for (i = 0; table[i].ogg; i++) {
462 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
463 (*cmt)[strlen(table[i].ogg)] == '=') {
464 hdr = table[i].mp;
465 val = *cmt + strlen(table[i].ogg) + 1;
469 if (hdr)
470 demux_info_add(d, hdr, val);
471 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
472 cmt++;
476 /// Calculate the timestamp and add the packet to the demux stream
477 // return 1 if the packet was added, 0 otherwise
478 static int demux_ogg_add_packet(demux_stream_t *ds, ogg_stream_t *os,
479 int id, ogg_packet *pack)
481 demuxer_t *d = ds->demuxer;
482 demux_packet_t *dp;
483 unsigned char *data;
484 float pts = 0;
485 int flags = 0;
486 int samplesize = 1;
488 // If packet is an comment header then we try to get comments at first
489 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7)) {
490 vorbis_info vi;
491 vorbis_comment vc;
493 vorbis_info_init(&vi);
494 vorbis_comment_init(&vc);
495 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
496 if (vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
497 demux_ogg_check_comments(d, os, id, &vc);
498 vorbis_comment_clear(&vc);
499 vorbis_info_clear(&vi);
501 if (os->text) {
502 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
503 demux_ogg_add_sub(os, pack);
504 return 0;
506 if (os->speex) {
507 // discard first two packets, they contain the header and comment
508 if (os->hdr_packets < 2) {
509 os->hdr_packets++;
510 return 0;
512 } else {
513 // If packet is an header we jump it except for vorbis and theora
514 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
515 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
516 // handled differently for each and every stream type. The joy! The joy!
517 if (!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
518 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
519 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
520 return 0;
523 // For vorbis packet the packet is the data, for other codec we must jump
524 // the header
525 if (ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
526 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
528 data = demux_ogg_read_packet(os, pack, &pts, &flags, samplesize);
529 if (!data)
530 return 0;
532 /// Clear subtitles if necessary (for broken files)
533 if (sub_clear_text(&ogg_sub, pts)) {
534 vo_sub = &ogg_sub;
535 vo_osd_changed(OSDTYPE_SUBTITLE);
537 /// Send the packet
538 dp = new_demux_packet(pack->bytes - (data - pack->packet));
539 memcpy(dp->buffer, data, pack->bytes - (data - pack->packet));
540 dp->pts = pts;
541 dp->flags = flags;
542 ds_add_packet(ds, dp);
543 mp_msg(MSGT_DEMUX, MSGL_DBG2,
544 "New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
545 dp, ds, pts, dp->len, flags);
546 return 1;
549 /// if -forceidx build a table of all syncpoints to make seeking easier
550 /// otherwise try to get at least the final_granulepos
551 static void demux_ogg_scan_stream(demuxer_t *demuxer)
553 ogg_demuxer_t *ogg_d = demuxer->priv;
554 stream_t *s = demuxer->stream;
555 ogg_sync_state *sync = &ogg_d->sync;
556 ogg_page *page = &ogg_d->page;
557 ogg_stream_state *oss;
558 ogg_stream_t *os;
559 ogg_packet op;
560 int np, sid, p, samplesize = 1;
561 off_t pos, last_pos;
563 pos = last_pos = demuxer->movi_start;
565 // Reset the stream
566 stream_seek(s, demuxer->movi_start);
567 ogg_sync_reset(sync);
569 // Get the serial number of the stream we use
570 if (demuxer->video->id >= 0) {
571 sid = demuxer->video->id;
572 } else if (demuxer->audio->id >= 0) {
573 sid = demuxer->audio->id;
574 if (((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
575 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
576 } else
577 return;
578 os = &ogg_d->subs[sid];
579 oss = &os->stream;
581 while (1) {
582 np = ogg_sync_pageseek(sync, page);
583 if (np < 0) { // We had to skip some bytes
584 if (index_mode == 2)
585 mp_msg(MSGT_DEMUX, MSGL_ERR,
586 "Bad page sync while building syncpoints table (%d)\n",
587 -np);
588 pos += -np;
589 continue;
591 if (np <= 0) { // We need more data
592 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
593 int len = stream_read(s, buf, BLOCK_SIZE);
595 if (len == 0 && s->eof)
596 break;
597 ogg_sync_wrote(sync, len);
598 continue;
600 // The page is ready
601 //ogg_sync_pageout(sync, page);
602 if (ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
603 pos += np;
604 continue;
606 if (ogg_stream_pagein(oss, page) != 0) {
607 mp_msg(MSGT_DEMUX, MSGL_ERR, "Pagein error ????\n");
608 pos += np;
609 continue;
611 p = 0;
612 while (ogg_stream_packetout(oss, &op) == 1) {
613 float pts;
614 int flags;
616 demux_ogg_read_packet(os, &op, &pts, &flags, samplesize);
617 if (op.granulepos >= 0) {
618 ogg_d->final_granulepos = op.granulepos;
619 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
620 ogg_d->initial_granulepos = op.granulepos;
621 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end - 2 * 270000) {
622 //the 270000 are just a wild guess
623 stream_seek(s, FFMAX(ogg_d->pos, demuxer->movi_end - 270000));
624 ogg_sync_reset(sync);
625 continue;
629 if (index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
630 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1)
631 break;
632 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints, (ogg_d->num_syncpoint + 1), sizeof(ogg_syncpoint_t));
633 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
634 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
635 ogg_d->num_syncpoint++;
637 p++;
639 if (p > 1 || (p == 1 && !ogg_page_continued(page)))
640 last_pos = pos;
641 pos += np;
642 if (index_mode == 2)
643 mp_msg(MSGT_DEMUX, MSGL_INFO, "Building syncpoint table %d%%\r",
644 (int)(pos * 100 / s->end_pos));
647 if (index_mode == 2) {
648 mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
649 mp_msg(MSGT_DEMUX, MSGL_V,
650 "Ogg syncpoints table builed: %d syncpoints\n",
651 ogg_d->num_syncpoint);
654 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg stream length (granulepos): %"PRId64"\n",
655 ogg_d->final_granulepos);
657 stream_reset(s);
658 stream_seek(s, demuxer->movi_start);
659 ogg_sync_reset(sync);
660 for (np = 0; np < ogg_d->num_sub; np++) {
661 ogg_stream_reset(&ogg_d->subs[np].stream);
662 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
665 // Get the first page
666 while (1) {
667 np = ogg_sync_pageout(sync, page);
668 if (np <= 0) { // We need more data
669 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
670 int len = stream_read(s, buf, BLOCK_SIZE);
672 if (len == 0 && s->eof) {
673 mp_msg(MSGT_DEMUX, MSGL_ERR, "EOF while trying to get the first page !!!!\n");
674 break;
676 ogg_sync_wrote(sync, len);
677 continue;
679 demux_ogg_get_page_stream(ogg_d, &oss);
680 ogg_stream_pagein(oss, page);
681 break;
685 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
687 int i, offset;
688 int ris, init_error = 0;
689 ogg_packet op[3];
690 unsigned char *buf[3];
691 unsigned char *ptr;
692 unsigned int len;
693 ogg_stream_t *os = &od->subs[sh->ds->id];
694 vorbis_comment vc;
696 vorbis_info_init(&os->vi);
697 vorbis_comment_init(&vc);
698 for (i = 0; i < 3; i++) {
699 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
700 mp_msg(MSGT_DEMUX, MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
701 if (op[i].bytes < 0) {
702 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
703 return;
705 buf[i] = malloc(op[i].bytes);
706 if (!buf[i])
707 return;
708 memcpy(buf[i], op[i].packet, op[i].bytes);
710 op[i].b_o_s = (i == 0);
711 ris = vorbis_synthesis_headerin(&os->vi, &vc, &op[i]);
712 if (ris < 0) {
713 init_error = 1;
714 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
717 vorbis_comment_clear(&vc);
718 if (!init_error)
719 os->vi_initialized = 1;
721 len = op[0].bytes + op[1].bytes + op[2].bytes;
722 sh->wf = calloc(1, sizeof(*sh->wf) + len + len / 255 + 64);
723 ptr = (unsigned char*)(sh->wf + 1);
725 ptr[0] = 2;
726 offset = 1;
727 offset += store_ughvlc(&ptr[offset], op[0].bytes);
728 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 1st len = %u\n", offset);
729 offset += store_ughvlc(&ptr[offset], op[1].bytes);
730 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, offset after 2nd len = %u\n", offset);
731 for (i = 0; i < 3; i++) {
732 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
733 memcpy(&ptr[offset], buf[i], op[i].bytes);
734 offset += op[i].bytes;
736 sh->wf->cbSize = offset;
737 mp_msg(MSGT_DEMUX, MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
738 sh->wf = realloc(sh->wf, sizeof(*sh->wf) + sh->wf->cbSize);
740 if (op[0].bytes >= 29) {
741 unsigned int br;
742 int nombr, minbr, maxbr;
744 ptr = buf[0];
745 sh->channels = ptr[11];
746 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
747 maxbr = AV_RL32(&ptr[16]); //max
748 nombr = AV_RL32(&ptr[20]); //nominal
749 minbr = AV_RL32(&ptr[24]); //minimum
751 if (maxbr == -1)
752 maxbr = 0;
753 if (nombr == -1)
754 nombr = 0;
755 if (minbr == -1)
756 minbr = 0;
758 br = maxbr / 8;
759 if (!br)
760 br = nombr / 8;
761 if (!br)
762 br = minbr / 8;
763 sh->wf->nAvgBytesPerSec = br;
764 sh->wf->wBitsPerSample = 16;
765 sh->samplesize = (sh->wf->wBitsPerSample + 7) / 8;
767 mp_msg(MSGT_DEMUX, MSGL_V,
768 "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
769 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec,
770 maxbr, nombr, minbr);
772 free(buf[2]);
773 free(buf[1]);
774 free(buf[0]);
777 /// Open an ogg physical stream
778 // Not static because it's used also in demuxer_avi.c
779 int demux_ogg_open(demuxer_t *demuxer)
781 ogg_demuxer_t *ogg_d;
782 stream_t *s;
783 char *buf;
784 int np, s_no, n_audio = 0, n_video = 0;
785 int audio_id = -1, video_id = -1, text_id = -1;
786 ogg_sync_state *sync;
787 ogg_page *page;
788 ogg_packet pack;
789 sh_audio_t *sh_a;
790 sh_video_t *sh_v;
792 #ifdef CONFIG_ICONV
793 subcp_open(NULL);
794 #endif
796 s = demuxer->stream;
798 demuxer->priv = ogg_d = calloc(1, sizeof(*ogg_d));
799 sync = &ogg_d->sync;
800 page = &ogg_d->page;
802 ogg_sync_init(sync);
804 while (1) {
805 /// Try to get a page
806 ogg_d->pos += ogg_d->last_size;
807 np = ogg_sync_pageseek(sync, page);
808 /// Error
809 if (np < 0) {
810 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg demuxer : Bad page sync\n");
811 goto err_out;
813 /// Need some more data
814 if (np == 0) {
815 int len;
817 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
818 len = stream_read(s, buf, BLOCK_SIZE);
819 if (len == 0 && s->eof) {
820 goto err_out;
822 ogg_sync_wrote(sync, len);
823 continue;
825 ogg_d->last_size = np;
826 // We got one page now
828 if (!ogg_page_bos(page)) { // It's not a beginning page
829 // Header parsing end here, we need to get the page otherwise it will be lost
830 int id = demux_ogg_get_page_stream(ogg_d, NULL);
831 if (id >= 0)
832 ogg_stream_pagein(&ogg_d->subs[id].stream, page);
833 else
834 mp_msg(MSGT_DEMUX, MSGL_ERR,
835 "Ogg : Warning found none bos page from unknown stream %d\n",
836 ogg_page_serialno(page));
837 break;
840 /// Init the data structure needed for a logical stream
841 ogg_d->subs = realloc_struct(ogg_d->subs, ogg_d->num_sub+1,
842 sizeof(ogg_stream_t));
843 memset(&ogg_d->subs[ogg_d->num_sub], 0, sizeof(ogg_stream_t));
844 /// Get the stream serial number
845 s_no = ogg_page_serialno(page);
846 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream, s_no);
847 mp_msg(MSGT_DEMUX, MSGL_DBG2,
848 "Ogg : Found a stream with serial=%d\n", s_no);
849 // Take the first page
850 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream, page);
851 // Get first packet of the page
852 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack);
854 // Reset our vars
855 sh_a = NULL;
856 sh_v = NULL;
858 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
860 // Check for Vorbis
861 if (pack.bytes >= 7 && !strncmp(&pack.packet[1], "vorbis", 6)) {
862 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
863 sh_a->format = FOURCC_VORBIS;
864 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
865 ogg_d->subs[ogg_d->num_sub].id = n_audio;
866 n_audio++;
867 mp_msg(MSGT_DEMUX, MSGL_INFO,
868 "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
869 ogg_d->num_sub, n_audio - 1);
870 } else if (pack.bytes >= 80 && !strncmp(pack.packet, "Speex", 5)) {
871 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
872 sh_a->wf = calloc(1, sizeof(*sh_a->wf) + pack.bytes);
873 sh_a->format = FOURCC_SPEEX;
874 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
875 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
876 sh_a->wf->wFormatTag = sh_a->format;
877 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
878 sh_a->wf->nBlockAlign = 0;
879 sh_a->wf->wBitsPerSample = 16;
880 sh_a->samplesize = 2;
881 sh_a->wf->cbSize = pack.bytes;
882 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
884 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
885 ogg_d->subs[ogg_d->num_sub].speex = 1;
886 ogg_d->subs[ogg_d->num_sub].id = n_audio;
887 n_audio++;
888 mp_msg(MSGT_DEMUX, MSGL_INFO,
889 "[Ogg] stream %d: audio (Speex), -aid %d\n",
890 ogg_d->num_sub, n_audio - 1);
892 // check for Theora
893 #ifdef CONFIG_OGGTHEORA
894 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
895 int errorCode = 0;
896 theora_info inf;
897 theora_comment cc;
899 theora_info_init (&inf);
900 theora_comment_init (&cc);
902 errorCode = theora_decode_header (&inf, &cc, &pack);
903 if (errorCode) {
904 mp_msg(MSGT_DEMUX, MSGL_ERR,
905 "Theora header parsing failed: %i \n", errorCode);
906 } else {
907 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
909 sh_v->bih = calloc(1, sizeof(*sh_v->bih));
910 sh_v->bih->biSize = sizeof(*sh_v->bih);
911 sh_v->bih->biCompression = sh_v->format = FOURCC_THEORA;
912 sh_v->fps = ((double)inf.fps_numerator) / (double)inf.fps_denominator;
913 sh_v->frametime = ((double)inf.fps_denominator) / (double)inf.fps_numerator;
914 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
915 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
916 sh_v->bih->biBitCount = 24;
917 sh_v->bih->biPlanes = 3;
918 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount / 8) * sh_v->bih->biWidth * sh_v->bih->biHeight);
919 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
920 ogg_d->subs[ogg_d->num_sub].theora = 1;
921 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
922 ogg_d->subs[ogg_d->num_sub].id = n_video;
923 n_video++;
924 mp_msg(MSGT_DEMUX, MSGL_INFO,
925 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
926 ogg_d->num_sub,
927 (int)inf.version_major,
928 (int)inf.version_minor,
929 (int)inf.version_subminor,
930 n_video - 1);
931 if (mp_msg_test(MSGT_HEADER, MSGL_V))
932 print_video_header(sh_v->bih, MSGL_V);
934 theora_comment_clear(&cc);
935 theora_info_clear(&inf);
936 #endif /* CONFIG_OGGTHEORA */
937 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
938 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
939 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
940 ogg_d->subs[ogg_d->num_sub].id = n_audio;
941 n_audio++;
942 ogg_d->subs[ogg_d->num_sub].flac = 1;
943 sh_a->wf = NULL;
944 mp_msg(MSGT_DEMUX, MSGL_INFO,
945 "[Ogg] stream %d: audio (FLAC), -aid %d\n",
946 ogg_d->num_sub, n_audio - 1);
947 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
948 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
949 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
950 ogg_d->subs[ogg_d->num_sub].id = n_audio;
951 n_audio++;
952 ogg_d->subs[ogg_d->num_sub].flac = 2;
953 sh_a->wf = calloc(1, sizeof(*sh_a->wf) + 34);
954 sh_a->wf->wFormatTag = sh_a->format;
955 sh_a->wf->cbSize = 34;
956 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
957 mp_msg(MSGT_DEMUX, MSGL_INFO,
958 "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
959 ogg_d->num_sub, n_audio - 1);
961 /// Check for old header
962 } else if (pack.bytes >= 142 &&
963 !strncmp(&pack.packet[1], "Direct Show Samples embedded in Ogg", 35)) {
965 // Old video header
966 if (AV_RL32(pack.packet + 96) == 0x05589f80 && pack.bytes >= 184) {
967 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
968 sh_v->bih = calloc(1, sizeof(*sh_v->bih));
969 sh_v->bih->biSize = sizeof(*sh_v->bih);
970 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(pack.packet[68], pack.packet[69],
971 pack.packet[70], pack.packet[71]);
972 sh_v->frametime = AV_RL64(pack.packet + 164) * 0.0000001;
973 sh_v->fps = 1 / sh_v->frametime;
974 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet + 176);
975 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet + 180);
976 sh_v->bih->biBitCount = AV_RL16(pack.packet + 182);
977 if (!sh_v->bih->biBitCount)
978 sh_v->bih->biBitCount = 24; // hack, FIXME
979 sh_v->bih->biPlanes = 1;
980 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
982 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
983 ogg_d->subs[ogg_d->num_sub].id = n_video;
984 n_video++;
985 mp_msg(MSGT_DEMUX, MSGL_INFO,
986 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
987 ogg_d->num_sub, pack.packet[68], pack.packet[69],
988 pack.packet[70], pack.packet[71], n_video - 1);
989 if (mp_msg_test(MSGT_HEADER, MSGL_V))
990 print_video_header(sh_v->bih, MSGL_V);
991 // Old audio header
992 } else if (AV_RL32(pack.packet + 96) == 0x05589F81) {
993 unsigned int extra_size;
995 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
996 extra_size = AV_RL16(pack.packet + 140);
997 sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size);
998 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet + 124);
999 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet + 126);
1000 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet + 128);
1001 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet + 132);
1002 sh_a->wf->nBlockAlign = AV_RL16(pack.packet + 136);
1003 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet + 138);
1004 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1005 sh_a->wf->cbSize = extra_size;
1006 if (extra_size > 0)
1007 memcpy(sh_a->wf + 1,
1008 pack.packet + 142, extra_size);
1010 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1011 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1012 n_audio++;
1013 mp_msg(MSGT_DEMUX, MSGL_INFO,
1014 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1015 ogg_d->num_sub, sh_a->format, n_audio - 1);
1016 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1017 print_wave_header(sh_a->wf, MSGL_V);
1018 } else
1019 mp_msg(MSGT_DEMUX, MSGL_WARN,
1020 "Ogg stream %d contains an old header but the header type is unknown\n",
1021 ogg_d->num_sub);
1023 // Check new header
1024 } else if ((*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
1025 pack.bytes >= (int)sizeof(stream_header) + 1) {
1026 stream_header *st = (stream_header*)(pack.packet + 1);
1027 /// New video header
1028 if (strncmp(st->streamtype, "video", 5) == 0) {
1029 sh_v = new_sh_video_vid(demuxer, ogg_d->num_sub, n_video);
1030 sh_v->bih = calloc(1, sizeof(*sh_v->bih));
1031 sh_v->bih->biSize = sizeof(*sh_v->bih);
1032 sh_v->bih->biCompression = sh_v->format = mmioFOURCC(st->subtype[0], st->subtype[1],
1033 st->subtype[2], st->subtype[3]);
1034 sh_v->frametime = AV_RL64(&st->time_unit) * 0.0000001;
1035 sh_v->fps = 1.0 / sh_v->frametime;
1036 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
1037 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1038 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1039 if (!sh_v->bih->biBitCount)
1040 sh_v->bih->biBitCount = 24; // hack, FIXME
1041 sh_v->bih->biPlanes = 1;
1042 sh_v->bih->biSizeImage = (sh_v->bih->biBitCount >> 3) * sh_v->bih->biWidth * sh_v->bih->biHeight;
1044 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
1045 ogg_d->subs[ogg_d->num_sub].id = n_video;
1046 n_video++;
1047 mp_msg(MSGT_DEMUX, MSGL_INFO,
1048 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1049 ogg_d->num_sub, st->subtype[0], st->subtype[1],
1050 st->subtype[2], st->subtype[3], n_video - 1);
1051 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1052 print_video_header(sh_v->bih, MSGL_V);
1053 /// New audio header
1054 } else if (strncmp(st->streamtype, "audio", 5) == 0) {
1055 char buffer[5];
1056 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1057 unsigned int extra_offset = 0;
1059 memcpy(buffer, st->subtype, 4);
1060 buffer[4] = '\0';
1062 /* Nasty workaround. stream_header.size seems not to contain the real
1063 size in all cases. There are four extra bytes that are unaccounted
1064 for in front of the real codec initialization data _at least_ for
1065 AAC. So far I've only seen those bytes being all 0, so we can
1066 just skip them here. */
1067 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1068 extra_size -= 4;
1069 extra_offset = 4;
1072 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
1073 sh_a->wf = calloc(1, sizeof(*sh_a->wf) + extra_size);
1074 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1075 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1076 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1077 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1078 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1079 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1080 sh_a->samplesize = (sh_a->wf->wBitsPerSample + 7) / 8;
1081 sh_a->wf->cbSize = extra_size;
1082 if (extra_size)
1083 memcpy(sh_a->wf+1,
1084 ((char *)(st+1))+extra_offset, extra_size);
1086 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1087 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1088 n_audio++;
1089 mp_msg(MSGT_DEMUX, MSGL_INFO,
1090 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1091 ogg_d->num_sub, sh_a->format, n_audio - 1);
1092 if (mp_msg_test(MSGT_HEADER, MSGL_V))
1093 print_wave_header(sh_a->wf, MSGL_V);
1095 /// Check for text (subtitles) header
1096 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1097 mp_msg(MSGT_DEMUX, MSGL_INFO,
1098 "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
1099 ogg_d->num_sub, ogg_d->n_text);
1100 ogg_d->subs[ogg_d->num_sub].samplerate = AV_RL64(&st->time_unit) / 10;
1101 ogg_d->subs[ogg_d->num_sub].text = 1;
1102 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1103 if (demuxer->sub->id == ogg_d->n_text)
1104 text_id = ogg_d->num_sub;
1105 new_sh_sub(demuxer, ogg_d->n_text);
1106 ogg_d->n_text++;
1107 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(*ogg_d->text_ids));
1108 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1109 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(*ogg_d->text_langs));
1110 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1111 //// Unknown header type
1112 } else
1113 mp_msg(MSGT_DEMUX, MSGL_ERR,
1114 "Ogg stream %d has a header marker but is of an unknown type\n",
1115 ogg_d->num_sub);
1116 /// Unknown (invalid ?) header
1117 } else
1118 mp_msg(MSGT_DEMUX, MSGL_ERR,
1119 "Ogg stream %d is of an unknown type\n",
1120 ogg_d->num_sub);
1122 if (sh_a || sh_v) {
1123 demux_stream_t *ds = NULL;
1124 if (sh_a) {
1125 // If the audio stream is not defined we took the first one
1126 if (demuxer->audio->id == -1) {
1127 demuxer->audio->id = n_audio - 1;
1128 //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
1130 /// Is it the stream we want
1131 if (demuxer->audio->id == n_audio - 1) {
1132 demuxer->audio->sh = sh_a;
1133 sh_a->ds = demuxer->audio;
1134 ds = demuxer->audio;
1135 audio_id = ogg_d->num_sub;
1138 if (sh_v) {
1139 /// Also for video
1140 if (demuxer->video->id == -1) {
1141 demuxer->video->id = n_video - 1;
1142 //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
1144 if (demuxer->video->id == n_video - 1) {
1145 demuxer->video->sh = sh_v;
1146 sh_v->ds = demuxer->video;
1147 ds = demuxer->video;
1148 video_id = ogg_d->num_sub;
1151 /// Add the header packets if the stream isn't seekable
1152 if (ds && !s->end_pos) {
1153 /// Finish the page, otherwise packets will be lost
1154 do {
1155 demux_ogg_add_packet(ds, &ogg_d->subs[ogg_d->num_sub],
1156 ogg_d->num_sub, &pack);
1157 } while (ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream, &pack) == 1);
1160 ogg_d->num_sub++;
1163 if (!n_video && !n_audio) {
1164 goto err_out;
1167 if (!n_video || video_id < 0)
1168 demuxer->video->id = -2;
1169 else
1170 demuxer->video->id = video_id;
1171 if (!n_audio || audio_id < 0)
1172 demuxer->audio->id = -2;
1173 else
1174 demuxer->audio->id = audio_id;
1175 /* Disable the subs only if there are no text streams at all.
1176 Otherwise the stream to display might be chosen later when the comment
1177 packet is encountered and the user used -slang instead of -sid. */
1178 if (!ogg_d->n_text)
1179 demuxer->sub->id = -2;
1180 else if (text_id >= 0) {
1181 demuxer->sub->id = text_id;
1182 mp_msg(MSGT_DEMUX, MSGL_V,
1183 "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1186 ogg_d->final_granulepos = 0;
1187 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1188 if (!s->end_pos) {
1189 demuxer->seekable = 0;
1190 } else {
1191 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1192 demuxer->movi_end = s->end_pos;
1193 demuxer->seekable = 1;
1194 demux_ogg_scan_stream(demuxer);
1196 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1197 ogg_d->initial_granulepos = 0;
1198 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1200 mp_msg(MSGT_DEMUX, MSGL_V,
1201 "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
1202 n_audio, n_audio > 1 ? "s" : "",
1203 n_video, n_video > 1 ? "s" : "",
1204 ogg_d->n_text, ogg_d->n_text > 1 ? "s" : "");
1206 sh_a = demuxer->audio->sh;
1207 if (sh_a && sh_a->format == FOURCC_VORBIS)
1208 fixup_vorbis_wf(sh_a, ogg_d);
1210 return DEMUXER_TYPE_OGG;
1212 err_out:
1213 return 0;
1216 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds)
1218 ogg_demuxer_t *ogg_d;
1219 stream_t *s;
1220 demux_stream_t *ds;
1221 ogg_sync_state *sync;
1222 ogg_stream_state *os;
1223 ogg_page *page;
1224 ogg_packet pack;
1225 int np = 0, id=0;
1227 s = d->stream;
1228 ogg_d = d->priv;
1229 sync = &ogg_d->sync;
1230 page = &ogg_d->page;
1232 /// Find the stream we are working on
1233 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1234 mp_msg(MSGT_DEMUX, MSGL_ERR, "Ogg demuxer : can't get current stream\n");
1235 return 0;
1238 while (1) {
1239 np = 0;
1240 ds = NULL;
1241 /// Try to get some packet from the current page
1242 while ((np = ogg_stream_packetout(os, &pack)) != 1) {
1243 /// No packet we go the next page
1244 if (np == 0) {
1245 while (1) {
1246 int pa, len;
1247 char *buf;
1249 ogg_d->pos += ogg_d->last_size;
1250 /// Get the next page from the physical stream
1251 while ((pa = ogg_sync_pageseek(sync, page)) <= 0) {
1252 /// Error : we skip some bytes
1253 if (pa < 0) {
1254 mp_msg(MSGT_DEMUX, MSGL_WARN,
1255 "Ogg : Page out not synced, we skip some bytes\n");
1256 ogg_d->pos -= pa;
1257 continue;
1259 /// We need more data
1260 buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1261 len = stream_read(s, buf, BLOCK_SIZE);
1262 if (len == 0 && s->eof) {
1263 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Ogg : Stream EOF !!!!\n");
1264 return 0;
1266 ogg_sync_wrote(sync, len);
1267 } /// Page loop
1268 ogg_d->last_size = pa;
1269 /// Find the page's logical stream
1270 if ((id = demux_ogg_get_page_stream(ogg_d, &os)) < 0) {
1271 mp_msg(MSGT_DEMUX, MSGL_ERR,
1272 "Ogg demuxer error : we met an unknown stream\n");
1273 return 0;
1275 /// Take the page
1276 if (ogg_stream_pagein(os, page) == 0)
1277 break;
1278 /// Page was invalid => retry
1279 mp_msg(MSGT_DEMUX, MSGL_WARN,
1280 "Ogg demuxer : got invalid page !!!!!\n");
1281 ogg_d->pos += ogg_d->last_size;
1283 } else /// Packet was corrupted
1284 mp_msg(MSGT_DEMUX, MSGL_WARN,
1285 "Ogg : bad packet in stream %d\n", id);
1286 } /// Packet loop
1288 /// Is the actual logical stream in use ?
1289 if (id == d->audio->id)
1290 ds = d->audio;
1291 else if (id == d->video->id)
1292 ds = d->video;
1293 else if (ogg_d->subs[id].text)
1294 ds = d->sub;
1296 if (ds) {
1297 if (!demux_ogg_add_packet(ds, &ogg_d->subs[id], id, &pack))
1298 continue; /// Unuseful packet, get another
1299 d->filepos = ogg_d->pos;
1300 return 1;
1302 } /// while (1)
1305 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1306 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1307 demuxer_t *init_avi_with_ogg(demuxer_t *demuxer)
1309 struct MPOpts *opts = demuxer->opts;
1310 demuxer_t *od;
1311 ogg_demuxer_t *ogg_d;
1312 stream_t *s;
1313 uint32_t hdrsizes[3];
1314 demux_packet_t *dp;
1315 sh_audio_t *sh_audio = demuxer->audio->sh;
1316 int np;
1317 uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
1318 int i;
1319 unsigned char *p = NULL, *buf;
1320 int plen;
1322 /// Check that the cbSize is big enough for the following reads
1323 if (sh_audio->wf->cbSize < 22 + 3 * 4) {
1324 mp_msg(MSGT_DEMUX, MSGL_ERR,
1325 "AVI Ogg : Initial audio header is too small !!!!!\n");
1326 goto fallback;
1328 /// Get the size of the 3 header packet
1329 extradata += 22;
1330 for (i = 0; i < 3; i++) {
1331 hdrsizes[i] = AV_RL32(extradata);
1332 extradata += 4;
1334 // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
1336 /// Check the size
1337 if (sh_audio->wf->cbSize < 22 + 3 * 4 + hdrsizes[0] + hdrsizes[1] + hdrsizes[2]) {
1338 mp_msg(MSGT_DEMUX, MSGL_ERR,
1339 "AVI Ogg : Audio header is too small !!!!!\n");
1340 goto fallback;
1343 // Build the ogg demuxer private datas
1344 ogg_d = calloc(1, sizeof(*ogg_d));
1345 ogg_d->num_sub = 1;
1346 ogg_d->subs = malloc(sizeof(*ogg_d->subs));
1347 ogg_d->subs[0].vorbis = 1;
1349 // Init the ogg physical stream
1350 ogg_sync_init(&ogg_d->sync);
1352 // Get the first page of the stream : we assume there only 1 logical stream
1353 while ((np = ogg_sync_pageout(&ogg_d->sync, &ogg_d->page)) <= 0 ) {
1354 if (np < 0) {
1355 mp_msg(MSGT_DEMUX, MSGL_ERR,
1356 "AVI Ogg error : Can't init using first stream packets\n");
1357 free(ogg_d);
1358 goto fallback;
1360 // Add some data
1361 plen = ds_get_packet(demuxer->audio, &p);
1362 buf = ogg_sync_buffer(&ogg_d->sync, plen);
1363 memcpy(buf, p, plen);
1364 ogg_sync_wrote(&ogg_d->sync, plen);
1366 // Init the logical stream
1367 mp_msg(MSGT_DEMUX, MSGL_DBG2,
1368 "AVI Ogg found page with serial %d\n",
1369 ogg_page_serialno(&ogg_d->page));
1370 ogg_stream_init(&ogg_d->subs[0].stream, ogg_page_serialno(&ogg_d->page));
1371 // Write the page
1372 ogg_stream_pagein(&ogg_d->subs[0].stream, &ogg_d->page);
1374 // Create the ds_stream and the ogg demuxer
1375 s = new_ds_stream(demuxer->audio);
1376 od = new_demuxer(opts, s, DEMUXER_TYPE_OGG, 0, -2, -2, NULL);
1378 /// Add the header packets in the ogg demuxer audio stream
1379 for (i = 0; i < 3; i++) {
1380 dp = new_demux_packet(hdrsizes[i]);
1381 memcpy(dp->buffer, extradata, hdrsizes[i]);
1382 ds_add_packet(od->audio, dp);
1383 extradata += hdrsizes[i];
1386 // Finish setting up the ogg demuxer
1387 od->priv = ogg_d;
1388 sh_audio = new_sh_audio(od, 0);
1389 od->audio->id = 0;
1390 od->video->id = -2;
1391 od->audio->sh = sh_audio;
1392 sh_audio->ds = od->audio;
1393 sh_audio->format = FOURCC_VORBIS;
1394 fixup_vorbis_wf(sh_audio, ogg_d);
1396 /// Return the joined demuxers
1397 return new_demuxers_demuxer(demuxer, od, demuxer);
1399 fallback:
1400 demuxer->audio->id = -2;
1401 return demuxer;
1405 static void demux_ogg_seek(demuxer_t *demuxer, float rel_seek_secs,
1406 float audio_delay, int flags)
1408 ogg_demuxer_t *ogg_d = demuxer->priv;
1409 ogg_sync_state *sync = &ogg_d->sync;
1410 ogg_page* page= &ogg_d->page;
1411 ogg_stream_state *oss;
1412 ogg_stream_t *os;
1413 demux_stream_t *ds;
1414 ogg_packet op;
1415 float rate;
1416 int i, sp, first, precision = 1, do_seek = 1;
1417 vorbis_info *vi = NULL;
1418 int64_t gp = 0, old_gp;
1419 off_t pos, old_pos;
1420 int np;
1421 int is_gp_valid;
1422 float pts;
1423 int is_keyframe;
1424 int samplesize = 1;
1425 ogg_int64_t granulepos_orig;
1427 if (demuxer->video->id >= 0) {
1428 ds = demuxer->video;
1429 rate = ogg_d->subs[ds->id].samplerate;
1430 } else {
1431 ds = demuxer->audio;
1432 os = &ogg_d->subs[ds->id];
1433 vi = &(os->vi);
1434 rate = (float)vi->rate;
1435 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1438 os = &ogg_d->subs[ds->id];
1439 oss = &os->stream;
1441 old_gp = os->lastpos;
1442 old_pos = ogg_d->pos;
1444 //calculate the granulepos to seek to
1445 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1446 if (flags & SEEK_FACTOR) {
1447 if (ogg_d->duration > 0)
1448 gp += ogg_d->duration * rel_seek_secs;
1449 else
1450 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1451 } else
1452 gp += rel_seek_secs * rate;
1453 if (gp < 0)
1454 gp = 0;
1456 //calculate the filepos to seek to
1457 if (ogg_d->syncpoints) {
1458 for (sp = 0; sp < ogg_d->num_syncpoint; sp++)
1459 if (ogg_d->syncpoints[sp].granulepos >= gp)
1460 break;
1462 if (sp >= ogg_d->num_syncpoint)
1463 return;
1464 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp - 1].granulepos)
1465 sp--;
1466 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1467 if (sp > 0 && gp < os->lastpos)
1468 sp--;
1469 if (sp < ogg_d->num_syncpoint - 1 && gp > os->lastpos)
1470 sp++;
1472 pos = ogg_d->syncpoints[sp].page_pos;
1473 precision = 0;
1474 } else {
1475 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1476 if (flags & SEEK_FACTOR)
1477 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1478 else {
1479 if (ogg_d->duration > 0) {
1480 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1481 } else if (os->lastpos > 0) {
1482 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1485 if (pos < 0)
1486 pos = 0;
1487 if (pos > (demuxer->movi_end - demuxer->movi_start))
1488 pos = demuxer->movi_end - demuxer->movi_start;
1489 } // if (ogg_d->syncpoints)
1491 while (1) {
1492 if (do_seek) {
1493 stream_seek(demuxer->stream, pos+demuxer->movi_start);
1494 ogg_sync_reset(sync);
1495 for (i = 0; i < ogg_d->num_sub; i++) {
1496 ogg_stream_reset(&ogg_d->subs[i].stream);
1497 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1499 ogg_d->pos = pos;
1500 ogg_d->last_size = 0;
1501 /* we just guess that we reached correct granulepos, in case a
1502 subsequent search occurs before we read a valid granulepos */
1503 os->lastpos = gp;
1504 first = !(ogg_d->syncpoints);
1505 do_seek=0;
1507 ogg_d->pos += ogg_d->last_size;
1508 ogg_d->last_size = 0;
1509 np = ogg_sync_pageseek(sync, page);
1511 if (np < 0)
1512 ogg_d->pos -= np;
1513 if (np <= 0) { // We need more data
1514 char *buf = ogg_sync_buffer(sync, BLOCK_SIZE);
1515 int len = stream_read(demuxer->stream, buf, BLOCK_SIZE);
1517 if (len == 0 && demuxer->stream->eof) {
1518 mp_msg(MSGT_DEMUX, MSGL_V, "EOF while trying to seek !!!!\n");
1519 return;
1521 ogg_sync_wrote(sync, len);
1522 continue;
1524 ogg_d->last_size = np;
1525 if (ogg_page_serialno(page) != oss->serialno)
1526 continue;
1528 if (ogg_stream_pagein(oss, page) != 0)
1529 continue;
1531 while (1) {
1532 np = ogg_stream_packetout(oss, &op);
1533 if (np < 0)
1534 continue;
1535 else if (np == 0)
1536 break;
1537 if (first) { /* Discard the first packet as it's probably broken,
1538 and we don't have any other means to decide whether it is
1539 complete or not. */
1540 first = 0;
1541 break;
1543 is_gp_valid = (op.granulepos >= 0);
1544 granulepos_orig=op.granulepos;
1545 demux_ogg_read_packet(os, &op, &pts, &is_keyframe, samplesize);
1546 if (precision && is_gp_valid) {
1547 precision--;
1548 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1549 //prepare another seek because we are off by more than 1s
1550 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1551 if (pos < 0)
1552 pos = 0;
1553 if (pos < demuxer->movi_end - demuxer->movi_start) {
1554 do_seek=1;
1555 break;
1559 if (is_gp_valid && pos > 0 && old_gp > gp
1560 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1561 /* prepare another seek because looking for a syncpoint
1562 destroyed the backward search */
1563 pos = old_pos - 1.5 * (old_pos - pos);
1564 if (pos < 0)
1565 pos = 0;
1566 if (pos < demuxer->movi_end - demuxer->movi_start) {
1567 do_seek=1;
1568 break;
1571 if (!precision && (is_keyframe || os->vorbis || os->speex)) {
1572 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1573 vo_sub = &ogg_sub;
1574 vo_osd_changed(OSDTYPE_SUBTITLE);
1576 op.granulepos=granulepos_orig;
1577 demux_ogg_add_packet(ds, os, ds->id, &op);
1578 return;
1583 mp_msg(MSGT_DEMUX, MSGL_ERR, "Can't find the good packet :(\n");
1586 static void demux_close_ogg(demuxer_t *demuxer)
1588 ogg_demuxer_t *ogg_d = demuxer->priv;
1589 ogg_stream_t *os = NULL;
1590 int i;
1592 if (!ogg_d)
1593 return;
1595 #ifdef CONFIG_ICONV
1596 subcp_close();
1597 #endif
1599 ogg_sync_clear(&ogg_d->sync);
1600 if (ogg_d->subs) {
1601 for (i = 0; i < ogg_d->num_sub; i++) {
1602 os = &ogg_d->subs[i];
1603 ogg_stream_clear(&os->stream);
1604 if (os->vi_initialized)
1605 vorbis_info_clear(&os->vi);
1607 free(ogg_d->subs);
1609 if (ogg_d->syncpoints)
1610 free(ogg_d->syncpoints);
1611 if (ogg_d->text_ids)
1612 free(ogg_d->text_ids);
1613 if (ogg_d->text_langs) {
1614 for (i = 0; i < ogg_d->n_text; i++)
1615 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1616 free(ogg_d->text_langs);
1618 free(ogg_d);
1621 static int demux_ogg_control(demuxer_t *demuxer, int cmd, void *arg)
1623 ogg_demuxer_t *ogg_d = demuxer->priv;
1624 ogg_stream_t *os;
1625 float rate;
1627 if (demuxer->video->id >= 0) {
1628 os = &ogg_d->subs[demuxer->video->id];
1629 rate = os->samplerate;
1630 } else {
1631 os = &ogg_d->subs[demuxer->audio->id];
1632 rate = os->vi.rate;
1635 switch(cmd) {
1636 case DEMUXER_CTRL_GET_TIME_LENGTH:
1637 if (ogg_d->duration <= 0)
1638 return DEMUXER_CTRL_DONTKNOW;
1639 *(double *)arg = (double)(ogg_d->duration) / rate;
1640 return DEMUXER_CTRL_GUESS;
1642 case DEMUXER_CTRL_GET_PERCENT_POS:
1643 if (ogg_d->duration <= 0)
1644 return DEMUXER_CTRL_DONTKNOW;
1645 *(int *)arg = ((os->lastpos - ogg_d->initial_granulepos) * 100) / ogg_d->duration;
1646 return DEMUXER_CTRL_OK;
1648 default:
1649 return DEMUXER_CTRL_NOTIMPL;
1653 const demuxer_desc_t demuxer_desc_ogg = {
1654 "Ogg demuxer",
1655 "ogg",
1656 "Ogg",
1657 "?",
1659 DEMUXER_TYPE_OGG,
1660 1, // safe autodetect
1661 demux_ogg_open,
1662 demux_ogg_fill_buffer,
1663 NULL,
1664 demux_close_ogg,
1665 demux_ogg_seek,
1666 demux_ogg_control