Merge svn changes up to r30879
[mplayer/kovensky.git] / libmpdemux / demux_ogg.c
blob840e53fe0207ef0ed4c6741dd227899a1627c237
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 "help_mp.h"
31 #include "stream/stream.h"
32 #include "demuxer.h"
33 #include "stheader.h"
34 #include "ffmpeg_files/intreadwrite.h"
35 #include "aviprint.h"
36 #include "demux_mov.h"
37 #include "demux_ogg.h"
39 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
40 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
41 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
43 #ifdef CONFIG_TREMOR
44 #include <tremor/ogg.h>
45 #include <tremor/ivorbiscodec.h>
46 #else
47 #include <ogg/ogg.h>
48 #include <vorbis/codec.h>
49 #endif
51 #ifdef CONFIG_OGGTHEORA
52 #include <theora/theora.h>
53 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
54 #endif
56 #define BLOCK_SIZE 4096
58 /* Theora decoder context : we won't be able to interpret granule positions
59 * without using theora_granule_time with the theora_state of the stream.
60 * This is duplicated in `vd_theora.c'; put this in a common header?
62 #ifdef CONFIG_OGGTHEORA
63 typedef struct theora_struct_st {
64 theora_state st;
65 theora_comment cc;
66 theora_info inf;
67 } theora_struct_t;
68 #endif
70 //// OggDS headers
71 // Header for the new header format
72 typedef struct stream_header_video
74 ogg_int32_t width;
75 ogg_int32_t height;
76 } stream_header_video;
78 typedef struct stream_header_audio
80 ogg_int16_t channels;
81 ogg_int16_t blockalign;
82 ogg_int32_t avgbytespersec;
83 } stream_header_audio;
85 typedef struct __attribute__((__packed__)) stream_header
87 char streamtype[8];
88 char subtype[4];
90 ogg_int32_t size; // size of the structure
92 ogg_int64_t time_unit; // in reference time
93 ogg_int64_t samples_per_unit;
94 ogg_int32_t default_len; // in media time
96 ogg_int32_t buffersize;
97 ogg_int16_t bits_per_sample;
99 ogg_int16_t padding;
101 union
103 // Video specific
104 stream_header_video video;
105 // Audio specific
106 stream_header_audio audio;
107 } sh;
108 } stream_header;
110 /// Our private datas
112 typedef struct ogg_syncpoint {
113 int64_t granulepos;
114 off_t page_pos;
115 } ogg_syncpoint_t;
117 /// A logical stream
118 typedef struct ogg_stream {
119 /// Timestamping stuff
120 float samplerate; /// granulpos 2 time
121 int64_t lastpos;
122 int32_t lastsize;
123 int keyframe_frequency_force;
125 // Logical stream state
126 ogg_stream_state stream;
127 int hdr_packets;
128 int vorbis;
129 int speex;
130 int theora;
131 int flac;
132 int text;
133 int id;
135 vorbis_info vi;
136 int vi_initialized;
138 void *ogg_d;
139 } ogg_stream_t;
141 typedef struct ogg_demuxer {
142 /// Physical stream state
143 ogg_sync_state sync;
144 /// Current page
145 ogg_page page;
146 /// Logical streams
147 ogg_stream_t *subs;
148 int num_sub;
149 ogg_syncpoint_t* syncpoints;
150 int num_syncpoint;
151 off_t pos, last_size;
152 int64_t initial_granulepos;
153 int64_t final_granulepos;
154 int64_t duration;
156 /* Used for subtitle switching. */
157 int n_text;
158 int *text_ids;
159 char **text_langs;
160 } ogg_demuxer_t;
162 #define NUM_VORBIS_HDR_PACKETS 3
164 /// Some defines from OggDS
165 #define PACKET_TYPE_HEADER 0x01
166 #define PACKET_TYPE_BITS 0x07
167 #define PACKET_LEN_BITS01 0xc0
168 #define PACKET_LEN_BITS2 0x02
169 #define PACKET_IS_SYNCPOINT 0x08
171 extern char *dvdsub_lang, *audio_lang;
173 //-------- subtitle support - should be moved to decoder layer, and queue
174 // - subtitles up in demuxer buffer...
176 #include "subreader.h"
177 #include "libvo/sub.h"
178 #define OGG_SUB_MAX_LINE 128
180 static subtitle ogg_sub;
181 //FILE* subout;
183 static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
185 int lcv;
186 char *packet = pack->packet;
188 if (pack->bytes < 4)
189 return;
190 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
191 (unsigned char)packet[0],
192 (unsigned char)packet[1],
193 (unsigned char)packet[2],
194 &packet[3]);
196 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
197 // Find data start
198 double endpts = MP_NOPTS_VALUE;
199 int32_t duration = 0;
200 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
201 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
202 lcv = 1 + hdrlen;
203 if (pack->bytes < lcv)
204 return;
205 for (i = hdrlen; i > 0; i--) {
206 duration <<= 8;
207 duration |= (unsigned char)packet[i];
209 if (hdrlen > 0 && duration > 0) {
210 float pts;
211 if(pack->granulepos == -1)
212 pack->granulepos = os->lastpos + os->lastsize;
213 pts = (float)pack->granulepos/(float)os->samplerate;
214 endpts = 1.0 + pts + (float)duration/1000.0;
216 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
217 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
220 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
221 ogg_sub.lines, ogg_sub.text[0]);
222 #ifdef CONFIG_ICONV
223 subcp_recode(&ogg_sub);
224 #endif
225 vo_sub = &ogg_sub;
226 vo_osd_changed(OSDTYPE_SUBTITLE);
230 // get the logical stream of the current page
231 // fill os if non NULL and return the stream id
232 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
233 int id,s_no;
234 ogg_page* page = &ogg_d->page;
236 s_no = ogg_page_serialno(page);
238 for(id= 0; id < ogg_d->num_sub ; id++) {
239 if(s_no == ogg_d->subs[id].stream.serialno)
240 break;
243 if(id == ogg_d->num_sub) {
244 // If we have only one vorbis stream allow the stream id to change
245 // it's normal on radio stream (each song have an different id).
246 // But we (or the codec?) should check that the samplerate, etc
247 // doesn't change (for radio stream it's ok)
248 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
249 ogg_stream_reset(&ogg_d->subs[0].stream);
250 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
251 id = 0;
252 } else
253 return -1;
256 if(os)
257 *os = &ogg_d->subs[id].stream;
259 return id;
263 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
264 unsigned char* data = pack->packet;
265 int size = pack->bytes;
267 *pts = MP_NOPTS_VALUE;
268 *flags = 0;
270 if(os->vorbis) {
271 if(*pack->packet & PACKET_TYPE_HEADER)
272 os->hdr_packets++;
273 else
275 vorbis_info *vi;
276 int32_t blocksize = 0;
278 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
279 vi = os->vi_initialized ? &os->vi : NULL;
280 if (vi)
281 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
282 // Calculate the timestamp if the packet don't have any
283 if(pack->granulepos == -1) {
284 pack->granulepos = os->lastpos;
285 if(os->lastsize > 0)
286 pack->granulepos += os->lastsize;
287 } else
288 *flags = 1;
289 if (vi)
290 *pts = pack->granulepos / (float)vi->rate;
291 os->lastsize = blocksize;
292 os->lastpos = pack->granulepos;
294 } else if (os->speex) {
295 // whole packet (default)
296 # ifdef CONFIG_OGGTHEORA
297 } else if (os->theora) {
298 /* we pass complete packets to theora, mustn't strip the header! */
299 os->lastsize = 1;
301 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
302 have theora_state st, until all header packets were passed to the
303 decoder. */
304 if (!size || !(*data&0x80))
306 int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
307 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
309 if (pack->granulepos >= 0)
311 os->lastpos = pack->granulepos >> keyframe_granule_shift;
312 os->lastpos += pack->granulepos & iframemask;
313 *flags = (pack->granulepos & iframemask) == 0;
315 else
317 os->lastpos++;
319 pack->granulepos = os->lastpos;
320 *pts = (double)os->lastpos / (double)os->samplerate;
322 #endif /* CONFIG_OGGTHEORA */
323 } else if (os->flac) {
324 /* we pass complete packets to flac, mustn't strip the header! */
325 if (os->flac == 2 && pack->packet[0] != 0xff)
326 return NULL;
327 } else {
328 if(*pack->packet & PACKET_TYPE_HEADER)
329 os->hdr_packets++;
330 else {
331 // Find data start
332 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
333 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
334 data = pack->packet + 1 + hdrlen;
335 // Calculate the timestamp
336 if(pack->granulepos == -1)
337 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
338 // If we already have a timestamp it can be a syncpoint
339 if(*pack->packet & PACKET_IS_SYNCPOINT)
340 *flags = 1;
341 *pts = pack->granulepos/os->samplerate;
342 // Save the packet length and timestamp
343 os->lastsize = 0;
344 while(hdrlen) {
345 os->lastsize <<= 8;
346 os->lastsize |= pack->packet[hdrlen];
347 hdrlen--;
349 os->lastpos = pack->granulepos;
352 return data;
355 // check if clang has substring from comma separated langlist
356 static int demux_ogg_check_lang(const char *clang, const char *langlist)
358 const char *c;
360 if (!langlist || !*langlist)
361 return 0;
362 while ((c = strchr(langlist, ',')))
364 if (!strncasecmp(clang, langlist, c - langlist))
365 return 1;
366 langlist = &c[1];
368 if (!strncasecmp(clang, langlist, strlen(langlist)))
369 return 1;
370 return 0;
373 /** \brief Change the current subtitle stream and return its ID.
375 \param demuxer The demuxer whose subtitle stream will be changed.
376 \param new_num The number of the new subtitle track. The number must be
377 between 0 and ogg_d->n_text - 1.
379 \returns The Ogg stream number ( = page serial number) of the newly selected
380 track.
382 static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
384 ogg_demuxer_t *ogg_d = demuxer->priv;
385 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
388 /** \brief Translate the ogg track number into the subtitle number.
389 * \param demuxer The demuxer about whose subtitles we are inquiring.
390 * \param id The ogg track number of the subtitle track.
392 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
393 ogg_demuxer_t *ogg_d = demuxer->priv;
394 int i;
395 for (i = 0; i < ogg_d->n_text; i++)
396 if (ogg_d->text_ids[i] == id) return i;
397 return -1;
400 /// Try to print out comments and also check for LANGUAGE= tag
401 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
403 const char *hdr, *val;
404 char **cmt = vc->user_comments;
405 int index, i;
406 ogg_demuxer_t *ogg_d = d->priv;
407 static const struct table {
408 const char *ogg;
409 const char *mp;
410 } table[] = {
411 { "ENCODED_USING", "Software" },
412 { "ENCODER_URL", "Encoder URL" },
413 { "TITLE", "Title" },
414 { "ARTIST", "Artist" },
415 { "COMMENT", "Comments" },
416 { "DATE", "Creation Date" },
417 { "GENRE", "Genre" },
418 { "ALBUM", "Album" },
419 { "TRACKNUMBER", "Track" },
420 { NULL, NULL },
423 while(*cmt)
425 hdr = NULL;
426 if (!strncasecmp(*cmt, "LANGUAGE=", 9))
428 val = *cmt + 9;
429 if (ogg_d->subs[id].text)
430 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
431 else if (id != d->video->id)
432 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
433 if (ogg_d->subs[id].text)
434 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
435 // copy this language name into the array
436 index = demux_ogg_sub_reverse_id(d, id);
437 if (index >= 0) {
438 sh_sub_t* sh;
439 // in case of malicious files with more than one lang per track:
440 if (ogg_d->text_langs[index]) 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) free(sh->lang);
444 if (sh) sh->lang = strdup(val);
446 // check for -slang if subs are uninitialized yet
447 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
449 d->sub->id = index;
450 d->opts->sub_id = index;
451 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
453 else
454 hdr = "Language";
456 else {
457 for (i = 0; table[i].ogg; i++)
459 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
460 (*cmt)[strlen(table[i].ogg)] == '=')
462 hdr = table[i].mp;
463 val = *cmt + strlen(table[i].ogg) + 1;
467 if (hdr)
468 demux_info_add(d, hdr, val);
469 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
470 cmt++;
474 /// Calculate the timestamp and add the packet to the demux stream
475 // return 1 if the packet was added, 0 otherwise
476 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
477 demuxer_t* d = ds->demuxer;
478 demux_packet_t* dp;
479 unsigned char* data;
480 float pts = 0;
481 int flags = 0;
482 int samplesize = 1;
484 // If packet is an comment header then we try to get comments at first
485 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
487 vorbis_info vi;
488 vorbis_comment vc;
490 vorbis_info_init(&vi);
491 vorbis_comment_init(&vc);
492 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
493 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
494 demux_ogg_check_comments(d, os, id, &vc);
495 vorbis_comment_clear(&vc);
496 vorbis_info_clear(&vi);
498 if (os->text) {
499 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
500 demux_ogg_add_sub(os,pack);
501 return 0;
503 if (os->speex) {
504 // discard first two packets, they contain the header and comment
505 if (os->hdr_packets < 2) {
506 os->hdr_packets++;
507 return 0;
509 } else
510 // If packet is an header we jump it except for vorbis and theora
511 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
512 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
513 // handled differently for each and every stream type. The joy! The joy!
514 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
515 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
516 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
517 return 0;
519 // For vorbis packet the packet is the data, for other codec we must jump
520 // the header
521 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
522 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
524 data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
525 if (!data)
526 return 0;
528 /// Clear subtitles if necessary (for broken files)
529 if (sub_clear_text(&ogg_sub, pts)) {
530 vo_sub = &ogg_sub;
531 vo_osd_changed(OSDTYPE_SUBTITLE);
533 /// Send the packet
534 dp = new_demux_packet(pack->bytes-(data-pack->packet));
535 memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
536 dp->pts = pts;
537 dp->flags = flags;
538 ds_add_packet(ds,dp);
539 mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
540 dp, ds, pts, dp->len, flags);
541 return 1;
544 /// if -forceidx build a table of all syncpoints to make seeking easier
545 /// otherwise try to get at least the final_granulepos
546 static void demux_ogg_scan_stream(demuxer_t *demuxer)
548 ogg_demuxer_t* ogg_d = demuxer->priv;
549 stream_t *s = demuxer->stream;
550 ogg_sync_state* sync = &ogg_d->sync;
551 ogg_page* page= &ogg_d->page;
552 ogg_stream_state* oss;
553 ogg_stream_t* os;
554 ogg_packet op;
555 int np,sid,p,samplesize=1;
556 off_t pos, last_pos;
557 pos = last_pos = demuxer->movi_start;
559 // Reset the stream
560 stream_seek(s,demuxer->movi_start);
561 ogg_sync_reset(sync);
563 // Get the serial number of the stream we use
564 if(demuxer->video->id >= 0) {
565 sid = demuxer->video->id;
567 else if(demuxer->audio->id >= 0) {
568 sid = demuxer->audio->id;
569 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
570 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
573 else return;
574 os = &ogg_d->subs[sid];
575 oss = &os->stream;
577 while(1) {
578 np = ogg_sync_pageseek(sync,page);
579 if(np < 0) { // We had to skip some bytes
580 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
581 pos += -np;
582 continue;
584 if(np <= 0) { // We need more data
585 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
586 int len = stream_read(s,buf,BLOCK_SIZE);
587 if(len == 0 && s->eof)
588 break;
589 ogg_sync_wrote(sync,len);
590 continue;
592 // The page is ready
593 //ogg_sync_pageout(sync,page);
594 if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
595 pos += np;
596 continue;
598 if(ogg_stream_pagein(oss,page) != 0) {
599 mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
600 pos += np;
601 continue;
603 p = 0;
604 while(ogg_stream_packetout(oss,&op) == 1) {
605 float pts;
606 int flags;
607 demux_ogg_read_packet(os,&op,&pts,&flags,samplesize);
608 if(op.granulepos >= 0) {
609 ogg_d->final_granulepos = op.granulepos;
610 if(ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
611 ogg_d->initial_granulepos = op.granulepos;
612 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end-2*270000) {
613 //the 270000 are just a wild guess
614 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
615 ogg_sync_reset(sync);
616 continue;
620 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
621 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
622 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
623 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
624 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
625 ogg_d->num_syncpoint++;
627 p++;
629 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
630 last_pos = pos;
631 pos += np;
632 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
634 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
636 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
637 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
639 stream_reset(s);
640 stream_seek(s,demuxer->movi_start);
641 ogg_sync_reset(sync);
642 for(np = 0 ; np < ogg_d->num_sub ; np++) {
643 ogg_stream_reset(&ogg_d->subs[np].stream);
644 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
648 // Get the first page
649 while(1) {
650 np = ogg_sync_pageout(sync,page);
651 if(np <= 0) { // We need more data
652 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
653 int len = stream_read(s,buf,BLOCK_SIZE);
654 if(len == 0 && s->eof) {
655 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
656 break;
659 ogg_sync_wrote(sync,len);
660 continue;
662 demux_ogg_get_page_stream(ogg_d,&oss);
663 ogg_stream_pagein(oss,page);
664 break;
669 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
671 int i, offset;
672 int ris, init_error = 0;
673 ogg_packet op[3];
674 unsigned char *buf[3];
675 unsigned char *ptr;
676 unsigned int len;
677 ogg_stream_t *os = &od->subs[sh->ds->id];
678 vorbis_comment vc;
680 vorbis_info_init(&os->vi);
681 vorbis_comment_init(&vc);
682 for(i = 0; i < 3; i++) {
683 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
684 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
685 if(op[i].bytes < 0) {
686 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
687 return;
689 buf[i] = malloc(op[i].bytes);
690 if(!buf[i])
691 return;
692 memcpy(buf[i], op[i].packet, op[i].bytes);
694 op[i].b_o_s = (i==0);
695 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
696 if(ris < 0) {
697 init_error = 1;
698 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
701 vorbis_comment_clear(&vc);
702 if(!init_error)
703 os->vi_initialized = 1;
705 len = op[0].bytes + op[1].bytes + op[2].bytes;
706 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
707 ptr = (unsigned char*) (sh->wf+1);
709 ptr[0] = 2;
710 offset = 1;
711 offset += store_ughvlc(&ptr[offset], op[0].bytes);
712 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
713 offset += store_ughvlc(&ptr[offset], op[1].bytes);
714 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
715 for(i = 0; i < 3; i++) {
716 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
717 memcpy(&ptr[offset], buf[i], op[i].bytes);
718 offset += op[i].bytes;
720 sh->wf->cbSize = offset;
721 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
722 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
724 if(op[0].bytes >= 29) {
725 unsigned int br;
726 int nombr, minbr, maxbr;
727 ptr = buf[0];
728 sh->channels = ptr[11];
729 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
730 maxbr = AV_RL32(&ptr[16]); //max
731 nombr = AV_RL32(&ptr[20]); //nominal
732 minbr = AV_RL32(&ptr[24]); //minimum
734 if(maxbr == -1)
735 maxbr = 0;
736 if(nombr == -1)
737 nombr = 0;
738 if(minbr == -1)
739 minbr = 0;
741 br = maxbr / 8;
742 if(!br)
743 br = nombr / 8;
744 if(!br)
745 br = minbr / 8;
746 sh->wf->nAvgBytesPerSec = br;
747 sh->wf->wBitsPerSample = 16;
748 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
750 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
751 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
753 free(buf[2]);
754 free(buf[1]);
755 free(buf[0]);
759 /// Open an ogg physical stream
760 // Not static because it's used also in demuxer_avi.c
761 int demux_ogg_open(demuxer_t* demuxer) {
762 ogg_demuxer_t* ogg_d;
763 stream_t *s;
764 char* buf;
765 int np,s_no, n_audio = 0, n_video = 0;
766 int audio_id = -1, video_id = -1, text_id = -1;
767 ogg_sync_state* sync;
768 ogg_page* page;
769 ogg_packet pack;
770 sh_audio_t* sh_a;
771 sh_video_t* sh_v;
773 #ifdef CONFIG_ICONV
774 subcp_open(NULL);
775 #endif
777 s = demuxer->stream;
779 demuxer->priv =
780 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
781 sync = &ogg_d->sync;
782 page = &ogg_d->page;
784 ogg_sync_init(sync);
786 while(1) {
787 /// Try to get a page
788 ogg_d->pos += ogg_d->last_size;
789 np = ogg_sync_pageseek(sync,page);
790 /// Error
791 if(np < 0) {
792 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
793 goto err_out;
795 /// Need some more data
796 if(np == 0) {
797 int len;
798 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
799 len = stream_read(s,buf,BLOCK_SIZE);
800 if(len == 0 && s->eof) {
801 goto err_out;
803 ogg_sync_wrote(sync,len);
804 continue;
806 ogg_d->last_size = np;
807 // We got one page now
809 if( ! ogg_page_bos(page) ) { // It's not a beginning page
810 // Header parsing end here, we need to get the page otherwise it will be lost
811 int id = demux_ogg_get_page_stream(ogg_d,NULL);
812 if(id >= 0)
813 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
814 else
815 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
816 break;
819 /// Init the data structure needed for a logical stream
820 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
821 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
822 /// Get the stream serial number
823 s_no = ogg_page_serialno(page);
824 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
825 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
826 // Take the first page
827 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
828 // Get first packet of the page
829 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
831 // Reset our vars
832 sh_a = NULL;
833 sh_v = NULL;
835 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
837 // Check for Vorbis
838 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
839 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
840 sh_a->format = FOURCC_VORBIS;
841 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
842 ogg_d->subs[ogg_d->num_sub].id = n_audio;
843 n_audio++;
844 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
845 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
846 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
847 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
848 sh_a->format = FOURCC_SPEEX;
849 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
850 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
851 sh_a->wf->wFormatTag = sh_a->format;
852 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
853 sh_a->wf->nBlockAlign = 0;
854 sh_a->wf->wBitsPerSample = 16;
855 sh_a->samplesize = 2;
856 sh_a->wf->cbSize = pack.bytes;
857 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
859 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
860 ogg_d->subs[ogg_d->num_sub].speex = 1;
861 ogg_d->subs[ogg_d->num_sub].id = n_audio;
862 n_audio++;
863 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
865 // check for Theora
866 # ifdef CONFIG_OGGTHEORA
867 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
868 int errorCode = 0;
869 theora_info inf;
870 theora_comment cc;
872 theora_info_init (&inf);
873 theora_comment_init (&cc);
875 errorCode = theora_decode_header (&inf, &cc, &pack);
876 if (errorCode)
877 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
878 errorCode);
879 else
881 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
883 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
884 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
885 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
886 sh_v->fps = ((double)inf.fps_numerator)/
887 (double)inf.fps_denominator;
888 sh_v->frametime = ((double)inf.fps_denominator)/
889 (double)inf.fps_numerator;
890 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
891 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
892 sh_v->bih->biBitCount = 24;
893 sh_v->bih->biPlanes = 3;
894 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
895 sh_v->bih->biWidth*sh_v->bih->biHeight);
896 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
897 ogg_d->subs[ogg_d->num_sub].theora = 1;
898 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
899 ogg_d->subs[ogg_d->num_sub].id = n_video;
900 n_video++;
901 mp_msg(MSGT_DEMUX,MSGL_INFO,
902 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
903 ogg_d->num_sub,
904 (int)inf.version_major,
905 (int)inf.version_minor,
906 (int)inf.version_subminor,
907 n_video - 1);
908 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
910 theora_comment_clear(&cc);
911 theora_info_clear(&inf);
912 # endif /* CONFIG_OGGTHEORA */
913 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
914 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
915 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
916 ogg_d->subs[ogg_d->num_sub].id = n_audio;
917 n_audio++;
918 ogg_d->subs[ogg_d->num_sub].flac = 1;
919 sh_a->wf = NULL;
920 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
921 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
922 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
923 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
924 ogg_d->subs[ogg_d->num_sub].id = n_audio;
925 n_audio++;
926 ogg_d->subs[ogg_d->num_sub].flac = 2;
927 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
928 sh_a->wf->wFormatTag = sh_a->format;
929 sh_a->wf->cbSize = 34;
930 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
931 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
933 /// Check for old header
934 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
936 // Old video header
937 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
938 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
939 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
940 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
941 sh_v->bih->biCompression=
942 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
943 pack.packet[70],pack.packet[71]);
944 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
945 sh_v->fps = 1/sh_v->frametime;
946 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
947 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
948 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
949 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
950 sh_v->bih->biPlanes=1;
951 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
953 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
954 ogg_d->subs[ogg_d->num_sub].id = n_video;
955 n_video++;
956 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
957 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
958 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
959 // Old audio header
960 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
961 unsigned int extra_size;
962 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
963 extra_size = AV_RL16(pack.packet+140);
964 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
965 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
966 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
967 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
968 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
969 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
970 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
971 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
972 sh_a->wf->cbSize = extra_size;
973 if(extra_size > 0)
974 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
976 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
977 ogg_d->subs[ogg_d->num_sub].id = n_audio;
978 n_audio++;
979 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1);
980 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
981 } else
982 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
984 // Check new header
985 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
986 pack.bytes >= (int)sizeof(stream_header)+1) {
987 stream_header *st = (stream_header*)(pack.packet+1);
988 /// New video header
989 if(strncmp(st->streamtype,"video",5) == 0) {
990 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
991 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
992 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
993 sh_v->bih->biCompression=
994 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
995 st->subtype[2],st->subtype[3]);
996 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
997 sh_v->fps = 1.0/sh_v->frametime;
998 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
999 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1000 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1001 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
1002 sh_v->bih->biPlanes=1;
1003 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
1005 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
1006 ogg_d->subs[ogg_d->num_sub].id = n_video;
1007 n_video++;
1008 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1009 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
1010 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
1011 /// New audio header
1012 } else if(strncmp(st->streamtype,"audio",5) == 0) {
1013 char buffer[5];
1014 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1015 unsigned int extra_offset = 0;
1017 memcpy(buffer,st->subtype,4);
1018 buffer[4] = '\0';
1020 /* Nasty workaround. stream_header.size seems not to contain the real
1021 size in all cases. There are four extra bytes that are unaccounted
1022 for in front of the real codec initialization data _at least_ for
1023 AAC. So far I've only seen those bytes being all 0, so we can
1024 just skip them here. */
1025 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1026 extra_size -= 4;
1027 extra_offset = 4;
1030 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1031 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1032 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1033 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1034 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1035 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1036 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1037 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1038 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1039 sh_a->wf->cbSize = extra_size;
1040 if(extra_size)
1041 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1043 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1044 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1045 n_audio++;
1046 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1);
1047 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1049 /// Check for text (subtitles) header
1050 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1051 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n", ogg_d->num_sub, ogg_d->n_text);
1052 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1053 ogg_d->subs[ogg_d->num_sub].text = 1;
1054 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1055 if (demuxer->sub->id == ogg_d->n_text)
1056 text_id = ogg_d->num_sub;
1057 new_sh_sub(demuxer, ogg_d->n_text);
1058 ogg_d->n_text++;
1059 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1060 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1061 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1062 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1063 //// Unknown header type
1064 } else
1065 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1066 /// Unknown (invalid ?) header
1067 } else
1068 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1070 if(sh_a || sh_v) {
1071 demux_stream_t* ds = NULL;
1072 if(sh_a) {
1073 // If the audio stream is not defined we took the first one
1074 if(demuxer->audio->id == -1) {
1075 demuxer->audio->id = n_audio - 1;
1076 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1078 /// Is it the stream we want
1079 if(demuxer->audio->id == n_audio - 1) {
1080 demuxer->audio->sh = sh_a;
1081 sh_a->ds = demuxer->audio;
1082 ds = demuxer->audio;
1083 audio_id = ogg_d->num_sub;
1086 if(sh_v) {
1087 /// Also for video
1088 if(demuxer->video->id == -1) {
1089 demuxer->video->id = n_video - 1;
1090 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1092 if(demuxer->video->id == n_video - 1) {
1093 demuxer->video->sh = sh_v;
1094 sh_v->ds = demuxer->video;
1095 ds = demuxer->video;
1096 video_id = ogg_d->num_sub;
1099 /// Add the header packets if the stream isn't seekable
1100 if(ds && !s->end_pos) {
1101 /// Finish the page, otherwise packets will be lost
1102 do {
1103 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1104 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1107 ogg_d->num_sub++;
1110 if(!n_video && !n_audio) {
1111 goto err_out;
1114 if(!n_video || video_id < 0)
1115 demuxer->video->id = -2;
1116 else
1117 demuxer->video->id = video_id;
1118 if(!n_audio || audio_id < 0)
1119 demuxer->audio->id = -2;
1120 else
1121 demuxer->audio->id = audio_id;
1122 /* Disable the subs only if there are no text streams at all.
1123 Otherwise the stream to display might be chosen later when the comment
1124 packet is encountered and the user used -slang instead of -sid. */
1125 if(!ogg_d->n_text)
1126 demuxer->sub->id = -2;
1127 else if (text_id >= 0) {
1128 demuxer->sub->id = text_id;
1129 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1132 ogg_d->final_granulepos=0;
1133 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1134 if(!s->end_pos)
1135 demuxer->seekable = 0;
1136 else {
1137 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1138 demuxer->movi_end = s->end_pos;
1139 demuxer->seekable = 1;
1140 demux_ogg_scan_stream(demuxer);
1142 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1143 ogg_d->initial_granulepos = 0;
1144 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1146 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":"");
1148 sh_a = demuxer->audio->sh;
1149 if(sh_a)
1150 if(sh_a->format == FOURCC_VORBIS)
1151 fixup_vorbis_wf(sh_a, ogg_d);
1153 return DEMUXER_TYPE_OGG;
1155 err_out:
1156 return 0;
1160 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1161 ogg_demuxer_t* ogg_d;
1162 stream_t *s;
1163 demux_stream_t *ds;
1164 ogg_sync_state* sync;
1165 ogg_stream_state* os;
1166 ogg_page* page;
1167 ogg_packet pack;
1168 int np = 0, id=0;
1170 s = d->stream;
1171 ogg_d = d->priv;
1172 sync = &ogg_d->sync;
1173 page = &ogg_d->page;
1175 /// Find the stream we are working on
1176 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1177 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1178 return 0;
1181 while(1) {
1182 np = 0;
1183 ds = NULL;
1184 /// Try to get some packet from the current page
1185 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1186 /// No packet we go the next page
1187 if(np == 0) {
1188 while(1) {
1189 int pa,len;
1190 char *buf;
1191 ogg_d->pos += ogg_d->last_size;
1192 /// Get the next page from the physical stream
1193 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1194 /// Error : we skip some bytes
1195 if(pa < 0) {
1196 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1197 ogg_d->pos -= pa;
1198 continue;
1200 /// We need more data
1201 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1202 len = stream_read(s,buf,BLOCK_SIZE);
1203 if(len == 0 && s->eof) {
1204 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1205 return 0;
1207 ogg_sync_wrote(sync,len);
1208 } /// Page loop
1209 ogg_d->last_size = pa;
1210 /// Find the page's logical stream
1211 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1212 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1213 return 0;
1215 /// Take the page
1216 if(ogg_stream_pagein(os,page) == 0)
1217 break;
1218 /// Page was invalid => retry
1219 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1220 ogg_d->pos += ogg_d->last_size;
1222 } else /// Packet was corrupted
1223 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1224 } /// Packet loop
1226 /// Is the actual logical stream in use ?
1227 if(id == d->audio->id)
1228 ds = d->audio;
1229 else if(id == d->video->id)
1230 ds = d->video;
1231 else if (ogg_d->subs[id].text)
1232 ds = d->sub;
1234 if(ds) {
1235 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1236 continue; /// Unuseful packet, get another
1237 d->filepos = ogg_d->pos;
1238 return 1;
1241 } /// while(1)
1245 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1246 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1247 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1248 struct MPOpts *opts = demuxer->opts;
1249 demuxer_t *od;
1250 ogg_demuxer_t *ogg_d;
1251 stream_t* s;
1252 uint32_t hdrsizes[3];
1253 demux_packet_t *dp;
1254 sh_audio_t *sh_audio = demuxer->audio->sh;
1255 int np;
1256 uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
1257 int i;
1258 unsigned char *p = NULL,*buf;
1259 int plen;
1261 /// Check that the cbSize is big enough for the following reads
1262 if(sh_audio->wf->cbSize < 22+3*4) {
1263 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1264 goto fallback;
1266 /// Get the size of the 3 header packet
1267 extradata += 22;
1268 for (i = 0; i < 3; i++) {
1269 hdrsizes[i] = AV_RL32(extradata);
1270 extradata += 4;
1272 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1274 /// Check the size
1275 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1276 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1277 goto fallback;
1280 // Build the ogg demuxer private datas
1281 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1282 ogg_d->num_sub = 1;
1283 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1284 ogg_d->subs[0].vorbis = 1;
1286 // Init the ogg physical stream
1287 ogg_sync_init(&ogg_d->sync);
1289 // Get the first page of the stream : we assume there only 1 logical stream
1290 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1291 if(np < 0) {
1292 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1293 free(ogg_d);
1294 goto fallback;
1296 // Add some data
1297 plen = ds_get_packet(demuxer->audio,&p);
1298 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1299 memcpy(buf,p,plen);
1300 ogg_sync_wrote(&ogg_d->sync,plen);
1302 // Init the logical stream
1303 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1304 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1305 // Write the page
1306 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1308 // Create the ds_stream and the ogg demuxer
1309 s = new_ds_stream(demuxer->audio);
1310 od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1312 /// Add the header packets in the ogg demuxer audio stream
1313 for (i = 0; i < 3; i++) {
1314 dp = new_demux_packet(hdrsizes[i]);
1315 memcpy(dp->buffer,extradata,hdrsizes[i]);
1316 ds_add_packet(od->audio,dp);
1317 extradata += hdrsizes[i];
1320 // Finish setting up the ogg demuxer
1321 od->priv = ogg_d;
1322 sh_audio = new_sh_audio(od,0);
1323 od->audio->id = 0;
1324 od->video->id = -2;
1325 od->audio->sh = sh_audio;
1326 sh_audio->ds = od->audio;
1327 sh_audio->format = FOURCC_VORBIS;
1328 fixup_vorbis_wf(sh_audio, ogg_d);
1330 /// Return the joined demuxers
1331 return new_demuxers_demuxer(demuxer,od,demuxer);
1333 fallback:
1334 demuxer->audio->id = -2;
1335 return demuxer;
1339 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1340 ogg_demuxer_t* ogg_d = demuxer->priv;
1341 ogg_sync_state* sync = &ogg_d->sync;
1342 ogg_page* page= &ogg_d->page;
1343 ogg_stream_state* oss;
1344 ogg_stream_t* os;
1345 demux_stream_t* ds;
1346 ogg_packet op;
1347 float rate;
1348 int i,sp,first,precision=1,do_seek=1;
1349 vorbis_info* vi = NULL;
1350 int64_t gp = 0, old_gp;
1351 off_t pos, old_pos;
1352 int np;
1353 int is_gp_valid;
1354 float pts;
1355 int is_keyframe;
1356 int samplesize=1;
1357 ogg_int64_t granulepos_orig;
1359 if(demuxer->video->id >= 0) {
1360 ds = demuxer->video;
1361 rate = ogg_d->subs[ds->id].samplerate;
1362 } else {
1363 ds = demuxer->audio;
1364 os = &ogg_d->subs[ds->id];
1365 vi = &(os->vi);
1366 rate = (float)vi->rate;
1367 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1370 os = &ogg_d->subs[ds->id];
1371 oss = &os->stream;
1373 old_gp = os->lastpos;
1374 old_pos = ogg_d->pos;
1376 //calculate the granulepos to seek to
1377 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1378 if(flags & SEEK_FACTOR) {
1379 if (ogg_d->duration > 0)
1380 gp += ogg_d->duration * rel_seek_secs;
1381 else
1382 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1383 } else
1384 gp += rel_seek_secs * rate;
1385 if (gp < 0) gp = 0;
1387 //calculate the filepos to seek to
1388 if(ogg_d->syncpoints) {
1389 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1390 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1393 if(sp >= ogg_d->num_syncpoint) return;
1394 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1395 sp--;
1396 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1397 if (sp > 0 && gp < os->lastpos) sp--;
1398 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1400 pos = ogg_d->syncpoints[sp].page_pos;
1401 precision = 0;
1402 } else {
1403 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1404 if(flags & SEEK_FACTOR)
1405 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1406 else {
1407 if (ogg_d->duration > 0) {
1408 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1409 } else if (os->lastpos > 0) {
1410 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1413 if (pos < 0) pos = 0;
1414 if (pos > (demuxer->movi_end - demuxer->movi_start))
1415 pos = demuxer->movi_end - demuxer->movi_start;
1416 } // if(ogg_d->syncpoints)
1418 while(1) {
1419 if (do_seek) {
1420 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1421 ogg_sync_reset(sync);
1422 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1423 ogg_stream_reset(&ogg_d->subs[i].stream);
1424 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1426 ogg_d->pos = pos;
1427 ogg_d->last_size = 0;
1428 /* we just guess that we reached correct granulepos, in case a
1429 subsequent search occurs before we read a valid granulepos */
1430 os->lastpos = gp;
1431 first = !(ogg_d->syncpoints);
1432 do_seek=0;
1434 ogg_d->pos += ogg_d->last_size;
1435 ogg_d->last_size = 0;
1436 np = ogg_sync_pageseek(sync,page);
1438 if(np < 0)
1439 ogg_d->pos -= np;
1440 if(np <= 0) { // We need more data
1441 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1442 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1443 if(len == 0 && demuxer->stream->eof) {
1444 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1445 return;
1447 ogg_sync_wrote(sync,len);
1448 continue;
1450 ogg_d->last_size = np;
1451 if(ogg_page_serialno(page) != oss->serialno)
1452 continue;
1454 if(ogg_stream_pagein(oss,page) != 0)
1455 continue;
1457 while(1) {
1458 np = ogg_stream_packetout(oss,&op);
1459 if(np < 0)
1460 continue;
1461 else if(np == 0)
1462 break;
1463 if (first) { /* Discard the first packet as it's probably broken,
1464 and we don't have any other means to decide whether it is
1465 complete or not. */
1466 first = 0;
1467 break;
1469 is_gp_valid = (op.granulepos >= 0);
1470 granulepos_orig=op.granulepos;
1471 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1472 if (precision && is_gp_valid) {
1473 precision--;
1474 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1475 //prepare another seek because we are off by more than 1s
1476 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1477 if (pos < 0) pos = 0;
1478 if (pos < demuxer->movi_end - demuxer->movi_start) {
1479 do_seek=1;
1480 break;
1484 if (is_gp_valid && pos > 0 && old_gp > gp
1485 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1486 /* prepare another seek because looking for a syncpoint
1487 destroyed the backward search */
1488 pos = old_pos - 1.5 * (old_pos - pos);
1489 if (pos < 0) pos = 0;
1490 if (pos < demuxer->movi_end - demuxer->movi_start) {
1491 do_seek=1;
1492 break;
1495 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1496 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1497 vo_sub = &ogg_sub;
1498 vo_osd_changed(OSDTYPE_SUBTITLE);
1500 op.granulepos=granulepos_orig;
1501 demux_ogg_add_packet(ds,os,ds->id,&op);
1502 return;
1507 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1511 static void demux_close_ogg(demuxer_t* demuxer) {
1512 ogg_demuxer_t* ogg_d = demuxer->priv;
1513 ogg_stream_t* os = NULL;
1514 int i;
1516 if(!ogg_d)
1517 return;
1519 #ifdef CONFIG_ICONV
1520 subcp_close();
1521 #endif
1523 ogg_sync_clear(&ogg_d->sync);
1524 if(ogg_d->subs)
1526 for (i = 0; i < ogg_d->num_sub; i++)
1528 os = &ogg_d->subs[i];
1529 ogg_stream_clear(&os->stream);
1530 if(os->vi_initialized)
1531 vorbis_info_clear(&os->vi);
1533 free(ogg_d->subs);
1535 if(ogg_d->syncpoints)
1536 free(ogg_d->syncpoints);
1537 if (ogg_d->text_ids)
1538 free(ogg_d->text_ids);
1539 if (ogg_d->text_langs) {
1540 for (i = 0; i < ogg_d->n_text; i++)
1541 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1542 free(ogg_d->text_langs);
1544 free(ogg_d);
1547 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1548 ogg_demuxer_t* ogg_d = demuxer->priv;
1549 ogg_stream_t* os;
1550 float rate;
1552 if(demuxer->video->id >= 0) {
1553 os = &ogg_d->subs[demuxer->video->id];
1554 rate = os->samplerate;
1555 } else {
1556 os = &ogg_d->subs[demuxer->audio->id];
1557 rate = os->vi.rate;
1561 switch(cmd) {
1562 case DEMUXER_CTRL_GET_TIME_LENGTH:
1563 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1564 *(double *)arg=(double)(ogg_d->duration) / rate;
1565 return DEMUXER_CTRL_GUESS;
1567 case DEMUXER_CTRL_GET_PERCENT_POS:
1568 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1569 *(int *)arg=((os->lastpos - ogg_d->initial_granulepos)*100) / ogg_d->duration;
1570 return DEMUXER_CTRL_OK;
1572 default:
1573 return DEMUXER_CTRL_NOTIMPL;
1579 const demuxer_desc_t demuxer_desc_ogg = {
1580 "Ogg demuxer",
1581 "ogg",
1582 "Ogg",
1583 "?",
1585 DEMUXER_TYPE_OGG,
1586 1, // safe autodetect
1587 demux_ogg_open,
1588 demux_ogg_fill_buffer,
1589 NULL,
1590 demux_close_ogg,
1591 demux_ogg_seek,
1592 demux_ogg_control