Merge svn changes up to r29150
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blob013bff5a76967d9663c589f40d664743963cbff5
2 #include "config.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <math.h>
9 #include <inttypes.h>
11 #include "options.h"
12 #include "mp_msg.h"
13 #include "help_mp.h"
14 #include "stream/stream.h"
15 #include "demuxer.h"
16 #include "stheader.h"
17 #include "libavutil/intreadwrite.h"
19 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
20 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
21 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
23 #ifdef CONFIG_TREMOR
24 #include <tremor/ogg.h>
25 #include <tremor/ivorbiscodec.h>
26 #else
27 #include <ogg/ogg.h>
28 #include <vorbis/codec.h>
29 #endif
31 #ifdef CONFIG_OGGTHEORA
32 #include <theora/theora.h>
33 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
34 #endif
36 #define BLOCK_SIZE 4096
38 /* Theora decoder context : we won't be able to interpret granule positions
39 * without using theora_granule_time with the theora_state of the stream.
40 * This is duplicated in `vd_theora.c'; put this in a common header?
42 #ifdef CONFIG_OGGTHEORA
43 typedef struct theora_struct_st {
44 theora_state st;
45 theora_comment cc;
46 theora_info inf;
47 } theora_struct_t;
48 #endif
50 //// OggDS headers
51 // Header for the new header format
52 typedef struct stream_header_video
54 ogg_int32_t width;
55 ogg_int32_t height;
56 } stream_header_video;
58 typedef struct stream_header_audio
60 ogg_int16_t channels;
61 ogg_int16_t blockalign;
62 ogg_int32_t avgbytespersec;
63 } stream_header_audio;
65 typedef struct __attribute__((__packed__)) stream_header
67 char streamtype[8];
68 char subtype[4];
70 ogg_int32_t size; // size of the structure
72 ogg_int64_t time_unit; // in reference time
73 ogg_int64_t samples_per_unit;
74 ogg_int32_t default_len; // in media time
76 ogg_int32_t buffersize;
77 ogg_int16_t bits_per_sample;
79 ogg_int16_t padding;
81 union
83 // Video specific
84 stream_header_video video;
85 // Audio specific
86 stream_header_audio audio;
87 } sh;
88 } stream_header;
90 /// Our private datas
92 typedef struct ogg_syncpoint {
93 int64_t granulepos;
94 off_t page_pos;
95 } ogg_syncpoint_t;
97 /// A logical stream
98 typedef struct ogg_stream {
99 /// Timestamping stuff
100 float samplerate; /// granulpos 2 time
101 int64_t lastpos;
102 int32_t lastsize;
103 int keyframe_frequency_force;
105 // Logical stream state
106 ogg_stream_state stream;
107 int hdr_packets;
108 int vorbis;
109 int speex;
110 int theora;
111 int flac;
112 int text;
113 int id;
115 vorbis_info vi;
116 int vi_initialized;
118 void *ogg_d;
119 } ogg_stream_t;
121 typedef struct ogg_demuxer {
122 /// Physical stream state
123 ogg_sync_state sync;
124 /// Current page
125 ogg_page page;
126 /// Logical streams
127 ogg_stream_t *subs;
128 int num_sub;
129 ogg_syncpoint_t* syncpoints;
130 int num_syncpoint;
131 off_t pos, last_size;
132 int64_t final_granulepos;
134 /* Used for subtitle switching. */
135 int n_text;
136 int *text_ids;
137 char **text_langs;
138 } ogg_demuxer_t;
140 #define NUM_VORBIS_HDR_PACKETS 3
142 /// Some defines from OggDS
143 #define PACKET_TYPE_HEADER 0x01
144 #define PACKET_TYPE_BITS 0x07
145 #define PACKET_LEN_BITS01 0xc0
146 #define PACKET_LEN_BITS2 0x02
147 #define PACKET_IS_SYNCPOINT 0x08
149 extern char *dvdsub_lang, *audio_lang;
151 //-------- subtitle support - should be moved to decoder layer, and queue
152 // - subtitles up in demuxer buffer...
154 #include "subreader.h"
155 #include "libvo/sub.h"
156 #define OGG_SUB_MAX_LINE 128
158 static subtitle ogg_sub;
159 //FILE* subout;
161 static void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) {
162 int lcv;
163 char *packet = pack->packet;
165 if (pack->bytes < 4)
166 return;
167 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
168 (unsigned char)packet[0],
169 (unsigned char)packet[1],
170 (unsigned char)packet[2],
171 &packet[3]);
173 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
174 // Find data start
175 double endpts = MP_NOPTS_VALUE;
176 int32_t duration = 0;
177 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
178 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
179 lcv = 1 + hdrlen;
180 if (pack->bytes < lcv)
181 return;
182 for (i = hdrlen; i > 0; i--) {
183 duration <<= 8;
184 duration |= (unsigned char)packet[i];
186 if (hdrlen > 0 && duration > 0) {
187 float pts;
188 if(pack->granulepos == -1)
189 pack->granulepos = os->lastpos + os->lastsize;
190 pts = (float)pack->granulepos/(float)os->samplerate;
191 endpts = 1.0 + pts + (float)duration/1000.0;
193 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
194 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
197 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
198 ogg_sub.lines, ogg_sub.text[0]);
199 #ifdef CONFIG_ICONV
200 subcp_recode(&ogg_sub);
201 #endif
202 vo_sub = &ogg_sub;
203 vo_osd_changed(OSDTYPE_SUBTITLE);
207 // get the logical stream of the current page
208 // fill os if non NULL and return the stream id
209 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
210 int id,s_no;
211 ogg_page* page = &ogg_d->page;
213 s_no = ogg_page_serialno(page);
215 for(id= 0; id < ogg_d->num_sub ; id++) {
216 if(s_no == ogg_d->subs[id].stream.serialno)
217 break;
220 if(id == ogg_d->num_sub) {
221 // If we have only one vorbis stream allow the stream id to change
222 // it's normal on radio stream (each song have an different id).
223 // But we (or the codec?) should check that the samplerate, etc
224 // doesn't change (for radio stream it's ok)
225 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
226 ogg_stream_reset(&ogg_d->subs[0].stream);
227 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
228 id = 0;
229 } else
230 return -1;
233 if(os)
234 *os = &ogg_d->subs[id].stream;
236 return id;
240 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
241 unsigned char* data = pack->packet;
243 *pts = 0;
244 *flags = 0;
246 if(os->vorbis) {
247 if(*pack->packet & PACKET_TYPE_HEADER)
248 os->hdr_packets++;
249 else if (os->vi_initialized)
251 vorbis_info *vi;
252 int32_t blocksize;
254 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
255 vi = &(os->vi);
256 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
257 // Calculate the timestamp if the packet don't have any
258 if(pack->granulepos == -1) {
259 pack->granulepos = os->lastpos;
260 if(os->lastsize > 0)
261 pack->granulepos += os->lastsize;
263 *pts = pack->granulepos / (float)vi->rate;
264 os->lastsize = blocksize;
265 os->lastpos = pack->granulepos;
267 } else if (os->speex) {
268 // whole packet (default)
269 # ifdef CONFIG_OGGTHEORA
270 } else if (os->theora) {
271 /* we pass complete packets to theora, mustn't strip the header! */
272 os->lastsize = 1;
274 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
275 have theora_state st, until all header packets were passed to the
276 decoder. */
277 if (!(*data&0x80))
279 int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
280 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
282 if (pack->granulepos >= 0)
284 os->lastpos = pack->granulepos >> keyframe_granule_shift;
285 os->lastpos += pack->granulepos & iframemask;
286 *flags = (pack->granulepos & iframemask) == 0;
288 else
290 os->lastpos++;
292 pack->granulepos = os->lastpos;
293 *pts = (double)os->lastpos / (double)os->samplerate;
295 #endif /* CONFIG_OGGTHEORA */
296 } else if (os->flac) {
297 /* we pass complete packets to flac, mustn't strip the header! */
298 if (os->flac == 2 && pack->packet[0] != 0xff)
299 return NULL;
300 } else {
301 if(*pack->packet & PACKET_TYPE_HEADER)
302 os->hdr_packets++;
303 else {
304 // Find data start
305 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
306 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
307 data = pack->packet + 1 + hdrlen;
308 // Calculate the timestamp
309 if(pack->granulepos == -1)
310 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
311 // If we already have a timestamp it can be a syncpoint
312 if(*pack->packet & PACKET_IS_SYNCPOINT)
313 *flags = 1;
314 *pts = pack->granulepos/os->samplerate;
315 // Save the packet length and timestamp
316 os->lastsize = 0;
317 while(hdrlen) {
318 os->lastsize <<= 8;
319 os->lastsize |= pack->packet[hdrlen];
320 hdrlen--;
322 os->lastpos = pack->granulepos;
325 return data;
328 // check if clang has substring from comma separated langlist
329 static int demux_ogg_check_lang(const char *clang, const char *langlist)
331 const char *c;
333 if (!langlist || !*langlist)
334 return 0;
335 while ((c = strchr(langlist, ',')))
337 if (!strncasecmp(clang, langlist, c - langlist))
338 return 1;
339 langlist = &c[1];
341 if (!strncasecmp(clang, langlist, strlen(langlist)))
342 return 1;
343 return 0;
346 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id);
348 /// Try to print out comments and also check for LANGUAGE= tag
349 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
351 const char *hdr, *val;
352 char **cmt = vc->user_comments;
353 int index, i;
354 ogg_demuxer_t *ogg_d = d->priv;
355 static const struct table {
356 const char *ogg;
357 const char *mp;
358 } table[] = {
359 { "ENCODED_USING", "Software" },
360 { "ENCODER_URL", "Encoder URL" },
361 { "TITLE", "Name" },
362 { "ARTIST", "Artist" },
363 { "COMMENT", "Comments" },
364 { "DATE", "Creation Date" },
365 { "GENRE", "Genre" },
366 { "ALBUM", "Album" },
367 { "TRACKNUMBER", "Track" },
368 { NULL, NULL },
371 while(*cmt)
373 hdr = NULL;
374 if (!strncasecmp(*cmt, "LANGUAGE=", 9))
376 val = *cmt + 9;
377 if (ogg_d->subs[id].text)
378 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
379 else if (id != d->video->id)
380 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
381 if (ogg_d->subs[id].text)
382 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
383 // copy this language name into the array
384 index = demux_ogg_sub_reverse_id(d, id);
385 if (index >= 0) {
386 sh_sub_t* sh;
387 // in case of malicious files with more than one lang per track:
388 if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
389 ogg_d->text_langs[index] = strdup(val);
390 sh = d->s_streams[index];
391 if (sh && sh->lang) free(sh->lang);
392 if (sh) sh->lang = strdup(val);
394 // check for -slang if subs are uninitialized yet
395 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
397 d->sub->id = index;
398 d->opts->sub_id = index;
399 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
401 else
402 hdr = "Language";
404 else {
405 for (i = 0; table[i].ogg; i++)
407 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
408 (*cmt)[strlen(table[i].ogg)] == '=')
410 hdr = table[i].mp;
411 val = *cmt + strlen(table[i].ogg) + 1;
415 if (hdr)
416 demux_info_add(d, hdr, val);
417 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
418 cmt++;
422 /// Calculate the timestamp and add the packet to the demux stream
423 // return 1 if the packet was added, 0 otherwise
424 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
425 demuxer_t* d = ds->demuxer;
426 demux_packet_t* dp;
427 unsigned char* data;
428 float pts = 0;
429 int flags = 0;
430 int samplesize = 1;
432 // If packet is an comment header then we try to get comments at first
433 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
435 vorbis_info vi;
436 vorbis_comment vc;
438 vorbis_info_init(&vi);
439 vorbis_comment_init(&vc);
440 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
441 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
442 demux_ogg_check_comments(d, os, id, &vc);
443 vorbis_comment_clear(&vc);
444 vorbis_info_clear(&vi);
446 if (os->text) {
447 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
448 demux_ogg_add_sub(os,pack);
449 return 0;
451 if (os->speex) {
452 // discard first two packets, they contain the header and comment
453 if (os->hdr_packets < 2) {
454 os->hdr_packets++;
455 return 0;
457 } else
458 // If packet is an header we jump it except for vorbis and theora
459 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
460 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
461 // handled differently for each and every stream type. The joy! The joy!
462 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
463 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
464 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
465 return 0;
467 // For vorbis packet the packet is the data, for other codec we must jump
468 // the header
469 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
470 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
472 data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
473 if (!data)
474 return 0;
476 /// Clear subtitles if necessary (for broken files)
477 if (sub_clear_text(&ogg_sub, pts)) {
478 vo_sub = &ogg_sub;
479 vo_osd_changed(OSDTYPE_SUBTITLE);
481 /// Send the packet
482 dp = new_demux_packet(pack->bytes-(data-pack->packet));
483 memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
484 dp->pts = pts;
485 dp->flags = flags;
486 ds_add_packet(ds,dp);
487 mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
488 dp, ds, pts, dp->len, flags);
489 return 1;
492 /// if -forceidx build a table of all syncpoints to make seeking easier
493 /// otherwise try to get at least the final_granulepos
494 static void demux_ogg_scan_stream(demuxer_t* demuxer) {
495 ogg_demuxer_t* ogg_d = demuxer->priv;
496 stream_t *s = demuxer->stream;
497 ogg_sync_state* sync = &ogg_d->sync;
498 ogg_page* page= &ogg_d->page;
499 ogg_stream_state* oss;
500 ogg_stream_t* os;
501 ogg_packet op;
502 int np,sid,p,samplesize=1;
503 off_t pos, last_pos;
504 pos = last_pos = demuxer->movi_start;
506 // Reset the stream
507 if(index_mode == 2) {
508 stream_seek(s,demuxer->movi_start);
509 } else {
510 //the 270000 are just a wild guess
511 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
513 ogg_sync_reset(sync);
515 // Get the serial number of the stream we use
516 if(demuxer->video->id >= 0) {
517 sid = demuxer->video->id;
519 else if(demuxer->audio->id >= 0) {
520 sid = demuxer->audio->id;
521 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
522 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
525 else return;
526 os = &ogg_d->subs[sid];
527 oss = &os->stream;
529 while(1) {
530 np = ogg_sync_pageseek(sync,page);
531 if(np < 0) { // We had to skip some bytes
532 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
533 pos += -np;
534 continue;
536 if(np <= 0) { // We need more data
537 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
538 int len = stream_read(s,buf,BLOCK_SIZE);
539 if(len == 0 && s->eof)
540 break;
541 ogg_sync_wrote(sync,len);
542 continue;
544 // The page is ready
545 //ogg_sync_pageout(sync,page);
546 if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
547 pos += np;
548 continue;
550 if(ogg_stream_pagein(oss,page) != 0) {
551 mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
552 pos += np;
553 continue;
555 p = 0;
556 while(ogg_stream_packetout(oss,&op) == 1) {
557 float pts;
558 int flags;
559 demux_ogg_read_packet(os,&op,&pts,&flags,samplesize);
560 if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;
561 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
562 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
563 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
564 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
565 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
566 ogg_d->num_syncpoint++;
568 p++;
570 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
571 last_pos = pos;
572 pos += np;
573 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
575 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
577 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
578 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
580 stream_reset(s);
581 stream_seek(s,demuxer->movi_start);
582 ogg_sync_reset(sync);
583 for(np = 0 ; np < ogg_d->num_sub ; np++) {
584 ogg_stream_reset(&ogg_d->subs[np].stream);
585 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
589 // Get the first page
590 while(1) {
591 np = ogg_sync_pageout(sync,page);
592 if(np <= 0) { // We need more data
593 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
594 int len = stream_read(s,buf,BLOCK_SIZE);
595 if(len == 0 && s->eof) {
596 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
597 break;
600 ogg_sync_wrote(sync,len);
601 continue;
603 demux_ogg_get_page_stream(ogg_d,&oss);
604 ogg_stream_pagein(oss,page);
605 break;
610 void print_wave_header(WAVEFORMATEX *h, int verbose_level);
611 void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
613 /* defined in demux_mov.c */
614 unsigned int store_ughvlc(unsigned char *s, unsigned int v);
616 /** \brief Change the current subtitle stream and return its ID.
618 \param demuxer The demuxer whose subtitle stream will be changed.
619 \param new_num The number of the new subtitle track. The number must be
620 between 0 and ogg_d->n_text - 1.
622 \returns The Ogg stream number ( = page serial number) of the newly selected
623 track.
625 int demux_ogg_sub_id(demuxer_t *demuxer, int index) {
626 ogg_demuxer_t *ogg_d = demuxer->priv;
627 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
630 /** \brief Translate the ogg track number into the subtitle number.
631 * \param demuxer The demuxer about whose subtitles we are inquiring.
632 * \param id The ogg track number of the subtitle track.
634 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
635 ogg_demuxer_t *ogg_d = demuxer->priv;
636 int i;
637 for (i = 0; i < ogg_d->n_text; i++)
638 if (ogg_d->text_ids[i] == id) return i;
639 return -1;
642 static void demux_close_ogg(demuxer_t* demuxer);
644 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
646 int i, offset;
647 int ris, init_error = 0;
648 ogg_packet op[3];
649 unsigned char *buf[3];
650 unsigned char *ptr;
651 unsigned int len;
652 ogg_stream_t *os = &od->subs[sh->ds->id];
653 vorbis_comment vc;
655 vorbis_info_init(&os->vi);
656 vorbis_comment_init(&vc);
657 for(i = 0; i < 3; i++) {
658 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
659 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
660 if(op[i].bytes < 0) {
661 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
662 return;
664 buf[i] = malloc(op[i].bytes);
665 if(!buf[i])
666 return;
667 memcpy(buf[i], op[i].packet, op[i].bytes);
669 op[i].b_o_s = (i==0);
670 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
671 if(ris < 0) {
672 init_error = 1;
673 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
676 vorbis_comment_clear(&vc);
677 if(!init_error)
678 os->vi_initialized = 1;
680 len = op[0].bytes + op[1].bytes + op[2].bytes;
681 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
682 ptr = (unsigned char*) (sh->wf+1);
684 ptr[0] = 2;
685 offset = 1;
686 offset += store_ughvlc(&ptr[offset], op[0].bytes);
687 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
688 offset += store_ughvlc(&ptr[offset], op[1].bytes);
689 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
690 for(i = 0; i < 3; i++) {
691 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
692 memcpy(&ptr[offset], buf[i], op[i].bytes);
693 offset += op[i].bytes;
695 sh->wf->cbSize = offset;
696 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
697 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
699 if(op[0].bytes >= 29) {
700 unsigned int br;
701 int nombr, minbr, maxbr;
702 ptr = buf[0];
703 sh->channels = ptr[11];
704 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
705 maxbr = AV_RL32(&ptr[16]); //max
706 nombr = AV_RL32(&ptr[20]); //nominal
707 minbr = AV_RL32(&ptr[24]); //minimum
709 if(maxbr == -1)
710 maxbr = 0;
711 if(nombr == -1)
712 nombr = 0;
713 if(minbr == -1)
714 minbr = 0;
716 br = maxbr / 8;
717 if(!br)
718 br = nombr / 8;
719 if(!br)
720 br = minbr / 8;
721 sh->wf->nAvgBytesPerSec = br;
722 sh->wf->wBitsPerSample = 16;
723 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
725 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",
726 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
728 free(buf[2]);
729 free(buf[1]);
730 free(buf[0]);
734 /// Open an ogg physical stream
735 // Not static because it's used also in demuxer_avi.c
736 int demux_ogg_open(demuxer_t* demuxer) {
737 ogg_demuxer_t* ogg_d;
738 stream_t *s;
739 char* buf;
740 int np,s_no, n_audio = 0, n_video = 0;
741 int audio_id = -1, video_id = -1, text_id = -1;
742 ogg_sync_state* sync;
743 ogg_page* page;
744 ogg_packet pack;
745 sh_audio_t* sh_a;
746 sh_video_t* sh_v;
748 #ifdef CONFIG_ICONV
749 subcp_open(NULL);
750 #endif
752 s = demuxer->stream;
754 demuxer->priv =
755 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
756 sync = &ogg_d->sync;
757 page = &ogg_d->page;
759 ogg_sync_init(sync);
761 while(1) {
762 /// Try to get a page
763 ogg_d->pos += ogg_d->last_size;
764 np = ogg_sync_pageseek(sync,page);
765 /// Error
766 if(np < 0) {
767 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
768 goto err_out;
770 /// Need some more data
771 if(np == 0) {
772 int len;
773 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
774 len = stream_read(s,buf,BLOCK_SIZE);
775 if(len == 0 && s->eof) {
776 goto err_out;
778 ogg_sync_wrote(sync,len);
779 continue;
781 ogg_d->last_size = np;
782 // We got one page now
784 if( ! ogg_page_bos(page) ) { // It's not a beginning page
785 // Header parsing end here, we need to get the page otherwise it will be lost
786 int id = demux_ogg_get_page_stream(ogg_d,NULL);
787 if(id >= 0)
788 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
789 else
790 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
791 break;
794 /// Init the data structure needed for a logical stream
795 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
796 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
797 /// Get the stream serial number
798 s_no = ogg_page_serialno(page);
799 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
800 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
801 // Take the first page
802 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
803 // Get first packet of the page
804 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
806 // Reset our vars
807 sh_a = NULL;
808 sh_v = NULL;
810 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
812 // Check for Vorbis
813 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
814 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
815 sh_a->format = FOURCC_VORBIS;
816 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
817 ogg_d->subs[ogg_d->num_sub].id = n_audio;
818 n_audio++;
819 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
820 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
821 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
822 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
823 sh_a->format = FOURCC_SPEEX;
824 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
825 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
826 sh_a->wf->wFormatTag = sh_a->format;
827 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
828 sh_a->wf->nBlockAlign = 0;
829 sh_a->wf->wBitsPerSample = 16;
830 sh_a->samplesize = 2;
831 sh_a->wf->cbSize = pack.bytes;
832 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
834 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
835 ogg_d->subs[ogg_d->num_sub].speex = 1;
836 ogg_d->subs[ogg_d->num_sub].id = n_audio;
837 n_audio++;
838 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
840 // check for Theora
841 # ifdef CONFIG_OGGTHEORA
842 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
843 int errorCode = 0;
844 theora_info inf;
845 theora_comment cc;
847 theora_info_init (&inf);
848 theora_comment_init (&cc);
850 errorCode = theora_decode_header (&inf, &cc, &pack);
851 if (errorCode)
852 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
853 errorCode);
854 else
856 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
858 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
859 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
860 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
861 sh_v->fps = ((double)inf.fps_numerator)/
862 (double)inf.fps_denominator;
863 sh_v->frametime = ((double)inf.fps_denominator)/
864 (double)inf.fps_numerator;
865 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
866 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
867 sh_v->bih->biBitCount = 24;
868 sh_v->bih->biPlanes = 3;
869 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
870 sh_v->bih->biWidth*sh_v->bih->biHeight);
871 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
872 ogg_d->subs[ogg_d->num_sub].theora = 1;
873 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
874 ogg_d->subs[ogg_d->num_sub].id = n_video;
875 n_video++;
876 mp_msg(MSGT_DEMUX,MSGL_INFO,
877 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
878 ogg_d->num_sub,
879 (int)inf.version_major,
880 (int)inf.version_minor,
881 (int)inf.version_subminor,
882 n_video - 1);
883 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
885 theora_comment_clear(&cc);
886 theora_info_clear(&inf);
887 # endif /* CONFIG_OGGTHEORA */
888 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
889 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
890 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
891 ogg_d->subs[ogg_d->num_sub].id = n_audio;
892 n_audio++;
893 ogg_d->subs[ogg_d->num_sub].flac = 1;
894 sh_a->wf = NULL;
895 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
896 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
897 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
898 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
899 ogg_d->subs[ogg_d->num_sub].id = n_audio;
900 n_audio++;
901 ogg_d->subs[ogg_d->num_sub].flac = 2;
902 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
903 sh_a->wf->wFormatTag = sh_a->format;
904 sh_a->wf->cbSize = 34;
905 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
906 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
908 /// Check for old header
909 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
911 // Old video header
912 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
913 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
914 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
915 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
916 sh_v->bih->biCompression=
917 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
918 pack.packet[70],pack.packet[71]);
919 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
920 sh_v->fps = 1/sh_v->frametime;
921 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
922 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
923 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
924 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
925 sh_v->bih->biPlanes=1;
926 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
928 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
929 ogg_d->subs[ogg_d->num_sub].id = n_video;
930 n_video++;
931 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
932 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
933 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
934 // Old audio header
935 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
936 unsigned int extra_size;
937 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
938 extra_size = AV_RL16(pack.packet+140);
939 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
940 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
941 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
942 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
943 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
944 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
945 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
946 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
947 sh_a->wf->cbSize = extra_size;
948 if(extra_size > 0)
949 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
951 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
952 ogg_d->subs[ogg_d->num_sub].id = n_audio;
953 n_audio++;
954 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);
955 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
956 } else
957 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
959 // Check new header
960 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
961 pack.bytes >= (int)sizeof(stream_header)+1) {
962 stream_header *st = (stream_header*)(pack.packet+1);
963 /// New video header
964 if(strncmp(st->streamtype,"video",5) == 0) {
965 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
966 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
967 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
968 sh_v->bih->biCompression=
969 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
970 st->subtype[2],st->subtype[3]);
971 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
972 sh_v->fps = 1.0/sh_v->frametime;
973 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
974 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
975 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
976 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
977 sh_v->bih->biPlanes=1;
978 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
980 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
981 ogg_d->subs[ogg_d->num_sub].id = n_video;
982 n_video++;
983 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
984 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
985 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
986 /// New audio header
987 } else if(strncmp(st->streamtype,"audio",5) == 0) {
988 char buffer[5];
989 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
990 unsigned int extra_offset = 0;
992 memcpy(buffer,st->subtype,4);
993 buffer[4] = '\0';
995 /* Nasty workaround. stream_header.size seems not to contain the real
996 size in all cases. There are four extra bytes that are unaccounted
997 for in front of the real codec initialization data _at least_ for
998 AAC. So far I've only seen those bytes being all 0, so we can
999 just skip them here. */
1000 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1001 extra_size -= 4;
1002 extra_offset = 4;
1005 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1006 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1007 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1008 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1009 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1010 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1011 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1012 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1013 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1014 sh_a->wf->cbSize = extra_size;
1015 if(extra_size)
1016 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1018 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1019 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1020 n_audio++;
1021 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);
1022 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1024 /// Check for text (subtitles) header
1025 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1026 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);
1027 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1028 ogg_d->subs[ogg_d->num_sub].text = 1;
1029 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1030 if (demuxer->sub->id == ogg_d->n_text)
1031 text_id = ogg_d->num_sub;
1032 new_sh_sub(demuxer, ogg_d->n_text);
1033 ogg_d->n_text++;
1034 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1035 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1036 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1037 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1038 //// Unknown header type
1039 } else
1040 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1041 /// Unknown (invalid ?) header
1042 } else
1043 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1045 if(sh_a || sh_v) {
1046 demux_stream_t* ds = NULL;
1047 if(sh_a) {
1048 // If the audio stream is not defined we took the first one
1049 if(demuxer->audio->id == -1) {
1050 demuxer->audio->id = n_audio - 1;
1051 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1053 /// Is it the stream we want
1054 if(demuxer->audio->id == n_audio - 1) {
1055 demuxer->audio->sh = sh_a;
1056 sh_a->ds = demuxer->audio;
1057 ds = demuxer->audio;
1058 audio_id = ogg_d->num_sub;
1061 if(sh_v) {
1062 /// Also for video
1063 if(demuxer->video->id == -1) {
1064 demuxer->video->id = n_video - 1;
1065 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1067 if(demuxer->video->id == n_video - 1) {
1068 demuxer->video->sh = sh_v;
1069 sh_v->ds = demuxer->video;
1070 ds = demuxer->video;
1071 video_id = ogg_d->num_sub;
1074 /// Add the header packets if the stream isn't seekable
1075 if(ds && !s->end_pos) {
1076 /// Finish the page, otherwise packets will be lost
1077 do {
1078 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1079 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1082 ogg_d->num_sub++;
1085 if(!n_video && !n_audio) {
1086 goto err_out;
1089 if(!n_video || video_id < 0)
1090 demuxer->video->id = -2;
1091 else
1092 demuxer->video->id = video_id;
1093 if(!n_audio || audio_id < 0)
1094 demuxer->audio->id = -2;
1095 else
1096 demuxer->audio->id = audio_id;
1097 /* Disable the subs only if there are no text streams at all.
1098 Otherwise the stream to display might be chosen later when the comment
1099 packet is encountered and the user used -slang instead of -sid. */
1100 if(!ogg_d->n_text)
1101 demuxer->sub->id = -2;
1102 else if (text_id >= 0) {
1103 demuxer->sub->id = text_id;
1104 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1107 ogg_d->final_granulepos=0;
1108 if(!s->end_pos)
1109 demuxer->seekable = 0;
1110 else {
1111 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1112 demuxer->movi_end = s->end_pos;
1113 demuxer->seekable = 1;
1114 demux_ogg_scan_stream(demuxer);
1117 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":"");
1119 sh_a = demuxer->audio->sh;
1120 if(sh_a)
1121 if(sh_a->format == FOURCC_VORBIS)
1122 fixup_vorbis_wf(sh_a, ogg_d);
1124 return DEMUXER_TYPE_OGG;
1126 err_out:
1127 return 0;
1131 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1132 ogg_demuxer_t* ogg_d;
1133 stream_t *s;
1134 demux_stream_t *ds;
1135 ogg_sync_state* sync;
1136 ogg_stream_state* os;
1137 ogg_page* page;
1138 ogg_packet pack;
1139 int np = 0, id=0;
1141 s = d->stream;
1142 ogg_d = d->priv;
1143 sync = &ogg_d->sync;
1144 page = &ogg_d->page;
1146 /// Find the stream we are working on
1147 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1148 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1149 return 0;
1152 while(1) {
1153 np = 0;
1154 ds = NULL;
1155 /// Try to get some packet from the current page
1156 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1157 /// No packet we go the next page
1158 if(np == 0) {
1159 while(1) {
1160 int pa,len;
1161 char *buf;
1162 ogg_d->pos += ogg_d->last_size;
1163 /// Get the next page from the physical stream
1164 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1165 /// Error : we skip some bytes
1166 if(pa < 0) {
1167 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1168 ogg_d->pos -= pa;
1169 continue;
1171 /// We need more data
1172 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1173 len = stream_read(s,buf,BLOCK_SIZE);
1174 if(len == 0 && s->eof) {
1175 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1176 return 0;
1178 ogg_sync_wrote(sync,len);
1179 } /// Page loop
1180 ogg_d->last_size = pa;
1181 /// Find the page's logical stream
1182 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1183 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1184 return 0;
1186 /// Take the page
1187 if(ogg_stream_pagein(os,page) == 0)
1188 break;
1189 /// Page was invalid => retry
1190 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1191 ogg_d->pos += ogg_d->last_size;
1193 } else /// Packet was corrupted
1194 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1195 } /// Packet loop
1197 /// Is the actual logical stream in use ?
1198 if(id == d->audio->id)
1199 ds = d->audio;
1200 else if(id == d->video->id)
1201 ds = d->video;
1202 else if (ogg_d->subs[id].text)
1203 ds = d->sub;
1205 if(ds) {
1206 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1207 continue; /// Unuseful packet, get another
1208 d->filepos = ogg_d->pos;
1209 return 1;
1212 } /// while(1)
1216 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1217 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1218 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1219 struct MPOpts *opts = demuxer->opts;
1220 demuxer_t *od;
1221 ogg_demuxer_t *ogg_d;
1222 stream_t* s;
1223 uint32_t hdrsizes[3];
1224 demux_packet_t *dp;
1225 sh_audio_t *sh_audio = demuxer->audio->sh;
1226 int np;
1227 uint8_t *extradata = sh_audio->wf + 1;
1228 int i;
1229 unsigned char *p = NULL,*buf;
1230 int plen;
1232 /// Check that the cbSize is big enough for the following reads
1233 if(sh_audio->wf->cbSize < 22+3*4) {
1234 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1235 goto fallback;
1237 /// Get the size of the 3 header packet
1238 extradata += 22;
1239 for (i = 0; i < 3; i++) {
1240 hdrsizes[i] = AV_RL32(extradata);
1241 extradata += 4;
1243 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1245 /// Check the size
1246 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1247 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1248 goto fallback;
1251 // Build the ogg demuxer private datas
1252 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1253 ogg_d->num_sub = 1;
1254 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1255 ogg_d->subs[0].vorbis = 1;
1257 // Init the ogg physical stream
1258 ogg_sync_init(&ogg_d->sync);
1260 // Get the first page of the stream : we assume there only 1 logical stream
1261 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1262 if(np < 0) {
1263 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1264 free(ogg_d);
1265 goto fallback;
1267 // Add some data
1268 plen = ds_get_packet(demuxer->audio,&p);
1269 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1270 memcpy(buf,p,plen);
1271 ogg_sync_wrote(&ogg_d->sync,plen);
1273 // Init the logical stream
1274 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1275 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1276 // Write the page
1277 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1279 // Create the ds_stream and the ogg demuxer
1280 s = new_ds_stream(demuxer->audio);
1281 od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1283 /// Add the header packets in the ogg demuxer audio stream
1284 for (i = 0; i < 3; i++) {
1285 dp = new_demux_packet(hdrsizes[i]);
1286 memcpy(dp->buffer,extradata,hdrsizes[i]);
1287 ds_add_packet(od->audio,dp);
1288 extradata += hdrsizes[i];
1291 // Finish setting up the ogg demuxer
1292 od->priv = ogg_d;
1293 sh_audio = new_sh_audio(od,0);
1294 od->audio->id = 0;
1295 od->video->id = -2;
1296 od->audio->sh = sh_audio;
1297 sh_audio->ds = od->audio;
1298 sh_audio->format = FOURCC_VORBIS;
1299 fixup_vorbis_wf(sh_audio, ogg_d);
1301 /// Return the joined demuxers
1302 return new_demuxers_demuxer(demuxer,od,demuxer);
1304 fallback:
1305 demuxer->audio->id = -2;
1306 return demuxer;
1310 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1311 ogg_demuxer_t* ogg_d = demuxer->priv;
1312 ogg_sync_state* sync = &ogg_d->sync;
1313 ogg_page* page= &ogg_d->page;
1314 ogg_stream_state* oss;
1315 ogg_stream_t* os;
1316 demux_stream_t* ds;
1317 ogg_packet op;
1318 float rate;
1319 int i,sp,first,precision=1,do_seek=1;
1320 vorbis_info* vi = NULL;
1321 int64_t gp = 0, old_gp;
1322 off_t pos, old_pos;
1323 int np;
1324 int is_gp_valid;
1325 float pts;
1326 int is_keyframe;
1327 int samplesize=1;
1328 ogg_int64_t granulepos_orig;
1330 if(demuxer->video->id >= 0) {
1331 ds = demuxer->video;
1332 rate = ogg_d->subs[ds->id].samplerate;
1333 } else {
1334 ds = demuxer->audio;
1335 os = &ogg_d->subs[ds->id];
1336 vi = &(os->vi);
1337 rate = (float)vi->rate;
1338 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1341 os = &ogg_d->subs[ds->id];
1342 oss = &os->stream;
1344 old_gp = os->lastpos;
1345 old_pos = ogg_d->pos;
1347 //calculate the granulepos to seek to
1348 gp = flags & SEEK_ABSOLUTE ? 0 : os->lastpos;
1349 if(flags & SEEK_FACTOR) {
1350 if (ogg_d->final_granulepos > 0)
1351 gp += ogg_d->final_granulepos * rel_seek_secs;
1352 else
1353 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1354 } else
1355 gp += rel_seek_secs * rate;
1356 if (gp < 0) gp = 0;
1358 //calculate the filepos to seek to
1359 if(ogg_d->syncpoints) {
1360 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1361 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1364 if(sp >= ogg_d->num_syncpoint) return;
1365 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1366 sp--;
1367 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1368 if (sp > 0 && gp < os->lastpos) sp--;
1369 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1371 pos = ogg_d->syncpoints[sp].page_pos;
1372 precision = 0;
1373 } else {
1374 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1375 if(flags & SEEK_FACTOR)
1376 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1377 else {
1378 if (ogg_d->final_granulepos > 0) {
1379 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);
1380 } else if (os->lastpos > 0) {
1381 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1384 if (pos < 0) pos = 0;
1385 if (pos > (demuxer->movi_end - demuxer->movi_start))
1386 pos = demuxer->movi_end - demuxer->movi_start;
1387 } // if(ogg_d->syncpoints)
1389 while(1) {
1390 if (do_seek) {
1391 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1392 ogg_sync_reset(sync);
1393 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1394 ogg_stream_reset(&ogg_d->subs[i].stream);
1395 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1397 ogg_d->pos = pos;
1398 ogg_d->last_size = 0;
1399 /* we just guess that we reached correct granulepos, in case a
1400 subsequent search occurs before we read a valid granulepos */
1401 os->lastpos = gp;
1402 first = !(ogg_d->syncpoints);
1403 do_seek=0;
1405 ogg_d->pos += ogg_d->last_size;
1406 ogg_d->last_size = 0;
1407 np = ogg_sync_pageseek(sync,page);
1409 if(np < 0)
1410 ogg_d->pos -= np;
1411 if(np <= 0) { // We need more data
1412 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1413 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1414 if(len == 0 && demuxer->stream->eof) {
1415 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1416 return;
1418 ogg_sync_wrote(sync,len);
1419 continue;
1421 ogg_d->last_size = np;
1422 if(ogg_page_serialno(page) != oss->serialno)
1423 continue;
1425 if(ogg_stream_pagein(oss,page) != 0)
1426 continue;
1428 while(1) {
1429 np = ogg_stream_packetout(oss,&op);
1430 if(np < 0)
1431 continue;
1432 else if(np == 0)
1433 break;
1434 if (first) { /* Discard the first packet as it's probably broken,
1435 and we don't have any other means to decide whether it is
1436 complete or not. */
1437 first = 0;
1438 break;
1440 is_gp_valid = (op.granulepos >= 0);
1441 granulepos_orig=op.granulepos;
1442 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1443 if (precision && is_gp_valid) {
1444 precision--;
1445 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1446 //prepare another seek because we are off by more than 1s
1447 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1448 if (pos < 0) pos = 0;
1449 if (pos < demuxer->movi_end - demuxer->movi_start) {
1450 do_seek=1;
1451 break;
1455 if (is_gp_valid && pos > 0 && old_gp > gp
1456 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1457 /* prepare another seek because looking for a syncpoint
1458 destroyed the backward search */
1459 pos = old_pos - 1.5 * (old_pos - pos);
1460 if (pos < 0) pos = 0;
1461 if (pos < demuxer->movi_end - demuxer->movi_start) {
1462 do_seek=1;
1463 break;
1466 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1467 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1468 vo_sub = &ogg_sub;
1469 vo_osd_changed(OSDTYPE_SUBTITLE);
1471 op.granulepos=granulepos_orig;
1472 demux_ogg_add_packet(ds,os,ds->id,&op);
1473 return;
1478 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1482 static void demux_close_ogg(demuxer_t* demuxer) {
1483 ogg_demuxer_t* ogg_d = demuxer->priv;
1484 ogg_stream_t* os = NULL;
1485 int i;
1487 if(!ogg_d)
1488 return;
1490 #ifdef CONFIG_ICONV
1491 subcp_close();
1492 #endif
1494 ogg_sync_clear(&ogg_d->sync);
1495 if(ogg_d->subs)
1497 for (i = 0; i < ogg_d->num_sub; i++)
1499 os = &ogg_d->subs[i];
1500 ogg_stream_clear(&os->stream);
1501 if(os->vi_initialized)
1502 vorbis_info_clear(&os->vi);
1504 free(ogg_d->subs);
1506 if(ogg_d->syncpoints)
1507 free(ogg_d->syncpoints);
1508 if (ogg_d->text_ids)
1509 free(ogg_d->text_ids);
1510 if (ogg_d->text_langs) {
1511 for (i = 0; i < ogg_d->n_text; i++)
1512 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1513 free(ogg_d->text_langs);
1515 free(ogg_d);
1518 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1519 ogg_demuxer_t* ogg_d = demuxer->priv;
1520 ogg_stream_t* os;
1521 float rate;
1523 if(demuxer->video->id >= 0) {
1524 os = &ogg_d->subs[demuxer->video->id];
1525 rate = os->samplerate;
1526 } else {
1527 os = &ogg_d->subs[demuxer->audio->id];
1528 rate = os->vi.rate;
1532 switch(cmd) {
1533 case DEMUXER_CTRL_GET_TIME_LENGTH:
1534 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1535 *(double *)arg=(double)ogg_d->final_granulepos / rate;
1536 return DEMUXER_CTRL_GUESS;
1538 case DEMUXER_CTRL_GET_PERCENT_POS:
1539 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1540 *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos;
1541 return DEMUXER_CTRL_OK;
1543 default:
1544 return DEMUXER_CTRL_NOTIMPL;
1550 const demuxer_desc_t demuxer_desc_ogg = {
1551 "Ogg demuxer",
1552 "ogg",
1553 "Ogg",
1554 "?",
1556 DEMUXER_TYPE_OGG,
1557 1, // safe autodetect
1558 demux_ogg_open,
1559 demux_ogg_fill_buffer,
1560 NULL,
1561 demux_close_ogg,
1562 demux_ogg_seek,
1563 demux_ogg_control