Add explanatory comments to the #endif part of multiple inclusion guards.
[mplayer/greg.git] / libmpdemux / demux_ogg.c
blob691d91377560b32116172257143616b42bbb5a41
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 "mp_msg.h"
12 #include "help_mp.h"
13 #include "stream/stream.h"
14 #include "demuxer.h"
15 #include "stheader.h"
16 #include "libavutil/intreadwrite.h"
18 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
19 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
20 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
22 #ifdef TREMOR
23 #include <tremor/ogg.h>
24 #include <tremor/ivorbiscodec.h>
25 #else
26 #include <ogg/ogg.h>
27 #include <vorbis/codec.h>
28 #endif
30 #ifdef HAVE_OGGTHEORA
31 #include <theora/theora.h>
32 extern int _ilog (unsigned int); /* defined in many places in theora/lib/ */
33 #endif
35 #define BLOCK_SIZE 4096
37 /* Theora decoder context : we won't be able to interpret granule positions
38 * without using theora_granule_time with the theora_state of the stream.
39 * This is duplicated in `vd_theora.c'; put this in a common header?
41 #ifdef HAVE_OGGTHEORA
42 typedef struct theora_struct_st {
43 theora_state st;
44 theora_comment cc;
45 theora_info inf;
46 } theora_struct_t;
47 #endif
49 //// OggDS headers
50 // Header for the new header format
51 typedef struct stream_header_video
53 ogg_int32_t width;
54 ogg_int32_t height;
55 } stream_header_video;
57 typedef struct stream_header_audio
59 ogg_int16_t channels;
60 ogg_int16_t blockalign;
61 ogg_int32_t avgbytespersec;
62 } stream_header_audio;
64 typedef struct __attribute__((__packed__)) stream_header
66 char streamtype[8];
67 char subtype[4];
69 ogg_int32_t size; // size of the structure
71 ogg_int64_t time_unit; // in reference time
72 ogg_int64_t samples_per_unit;
73 ogg_int32_t default_len; // in media time
75 ogg_int32_t buffersize;
76 ogg_int16_t bits_per_sample;
78 ogg_int16_t padding;
80 union
82 // Video specific
83 stream_header_video video;
84 // Audio specific
85 stream_header_audio audio;
86 } sh;
87 } stream_header;
89 /// Our private datas
91 typedef struct ogg_syncpoint {
92 int64_t granulepos;
93 off_t page_pos;
94 } ogg_syncpoint_t;
96 /// A logical stream
97 typedef struct ogg_stream {
98 /// Timestamping stuff
99 float samplerate; /// granulpos 2 time
100 int64_t lastpos;
101 int32_t lastsize;
103 // Logical stream state
104 ogg_stream_state stream;
105 int hdr_packets;
106 int vorbis;
107 int speex;
108 int theora;
109 int flac;
110 int text;
111 int id;
113 vorbis_info vi;
114 int vi_inited;
116 void *ogg_d;
117 } ogg_stream_t;
119 typedef struct ogg_demuxer {
120 /// Physical stream state
121 ogg_sync_state sync;
122 /// Current page
123 ogg_page page;
124 /// Logical streams
125 ogg_stream_t *subs;
126 int num_sub;
127 ogg_syncpoint_t* syncpoints;
128 int num_syncpoint;
129 off_t pos, last_size;
130 int64_t final_granulepos;
132 /* Used for subtitle switching. */
133 int n_text;
134 int *text_ids;
135 char **text_langs;
136 } ogg_demuxer_t;
138 #define NUM_VORBIS_HDR_PACKETS 3
140 /// Some defines from OggDS
141 #define PACKET_TYPE_HEADER 0x01
142 #define PACKET_TYPE_BITS 0x07
143 #define PACKET_LEN_BITS01 0xc0
144 #define PACKET_LEN_BITS2 0x02
145 #define PACKET_IS_SYNCPOINT 0x08
147 extern char *dvdsub_lang, *audio_lang;
148 extern int dvdsub_id;
150 //-------- subtitle support - should be moved to decoder layer, and queue
151 // - subtitles up in demuxer buffer...
153 #include "subreader.h"
154 #include "libvo/sub.h"
155 #define OGG_SUB_MAX_LINE 128
157 static subtitle ogg_sub;
158 //FILE* subout;
160 void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) {
161 int lcv;
162 char *packet = pack->packet;
164 if (pack->bytes < 4)
165 return;
166 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
167 (unsigned char)packet[0],
168 (unsigned char)packet[1],
169 (unsigned char)packet[2],
170 &packet[3]);
172 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
173 // Find data start
174 double endpts = MP_NOPTS_VALUE;
175 int32_t duration = 0;
176 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
177 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
178 lcv = 1 + hdrlen;
179 if (pack->bytes < lcv)
180 return;
181 for (i = hdrlen; i > 0; i--) {
182 duration <<= 8;
183 duration |= (unsigned char)packet[i];
185 if (hdrlen > 0 && duration > 0) {
186 float pts;
187 if(pack->granulepos == -1)
188 pack->granulepos = os->lastpos + os->lastsize;
189 pts = (float)pack->granulepos/(float)os->samplerate;
190 endpts = 1.0 + pts + (float)duration/1000.0;
192 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
193 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
196 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
197 ogg_sub.lines, ogg_sub.text[0]);
198 #ifdef USE_ICONV
199 subcp_recode(&ogg_sub);
200 #endif
201 vo_sub = &ogg_sub;
202 vo_osd_changed(OSDTYPE_SUBTITLE);
206 // get the logical stream of the current page
207 // fill os if non NULL and return the stream id
208 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
209 int id,s_no;
210 ogg_page* page = &ogg_d->page;
212 s_no = ogg_page_serialno(page);
214 for(id= 0; id < ogg_d->num_sub ; id++) {
215 if(s_no == ogg_d->subs[id].stream.serialno)
216 break;
219 if(id == ogg_d->num_sub) {
220 // If we have only one vorbis stream allow the stream id to change
221 // it's normal on radio stream (each song have an different id).
222 // But we (or the codec?) should check that the samplerate, etc
223 // doesn't change (for radio stream it's ok)
224 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
225 ogg_stream_reset(&ogg_d->subs[0].stream);
226 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
227 id = 0;
228 } else
229 return -1;
232 if(os)
233 *os = &ogg_d->subs[id].stream;
235 return id;
239 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,void *context,float* pts,int* flags, int samplesize) {
240 unsigned char* data = pack->packet;
242 *pts = 0;
243 *flags = 0;
245 if(os->vorbis) {
246 if(*pack->packet & PACKET_TYPE_HEADER)
247 os->hdr_packets++;
248 else if (os->vi_inited)
250 vorbis_info *vi;
251 int32_t blocksize;
253 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
254 vi = &(os->vi);
255 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
256 // Calculate the timestamp if the packet don't have any
257 if(pack->granulepos == -1) {
258 pack->granulepos = os->lastpos;
259 if(os->lastsize > 0)
260 pack->granulepos += os->lastsize;
262 *pts = pack->granulepos / (float)vi->rate;
263 os->lastsize = blocksize;
264 os->lastpos = pack->granulepos;
266 } else if (os->speex) {
267 // whole packet (default)
268 # ifdef HAVE_OGGTHEORA
269 } else if (os->theora) {
270 /* we pass complete packets to theora, mustn't strip the header! */
271 os->lastsize = 1;
273 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
274 have theora_state st, until all header packets were passed to the
275 decoder. */
276 if (context != NULL && !(*data&0x80))
278 theora_info *thi = ((theora_struct_t*)context)->st.i;
279 int keyframe_granule_shift=_ilog(thi->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 /* HAVE_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 // in case of malicious files with more than one lang per track:
387 if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
388 ogg_d->text_langs[index] = strdup(val);
390 // check for -slang if subs are uninitialized yet
391 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
393 d->sub->id = index;
394 dvdsub_id = index;
395 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
397 else
398 hdr = "Language";
400 else {
401 for (i = 0; table[i].ogg; i++)
403 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
404 (*cmt)[strlen(table[i].ogg)] == '=')
406 hdr = table[i].mp;
407 val = *cmt + strlen(table[i].ogg) + 1;
411 if (hdr)
412 demux_info_add(d, hdr, val);
413 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
414 cmt++;
418 /// Calculate the timestamp and add the packet to the demux stream
419 // return 1 if the packet was added, 0 otherwise
420 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
421 demuxer_t* d = ds->demuxer;
422 demux_packet_t* dp;
423 unsigned char* data;
424 float pts = 0;
425 int flags = 0;
426 void *context = NULL;
427 int samplesize = 1;
429 // If packet is an comment header then we try to get comments at first
430 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
432 vorbis_info vi;
433 vorbis_comment vc;
435 vorbis_info_init(&vi);
436 vorbis_comment_init(&vc);
437 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
438 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
439 demux_ogg_check_comments(d, os, id, &vc);
440 vorbis_comment_clear(&vc);
441 vorbis_info_clear(&vi);
443 if (os->text) {
444 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
445 demux_ogg_add_sub(os,pack);
446 return 0;
448 if (os->speex) {
449 // discard first two packets, they contain the header and comment
450 if (os->hdr_packets < 2) {
451 os->hdr_packets++;
452 return 0;
454 } else
455 // If packet is an header we jump it except for vorbis and theora
456 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
457 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
458 // handled differently for each and every stream type. The joy! The joy!
459 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
460 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
461 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
462 return 0;
464 // For vorbis packet the packet is the data, for other codec we must jump
465 // the header
466 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
467 context = ((sh_audio_t *)ds->sh)->context;
468 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
470 if (ds == d->video && ((sh_audio_t*)ds->sh)->format == FOURCC_THEORA)
471 context = ((sh_video_t *)ds->sh)->context;
472 data = demux_ogg_read_packet(os,pack,context,&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 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 void *context = NULL;
504 off_t pos, last_pos;
505 pos = last_pos = demuxer->movi_start;
507 // Reset the stream
508 if(index_mode == 2) {
509 stream_seek(s,demuxer->movi_start);
510 } else {
511 //the 270000 are just a wild guess
512 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
514 ogg_sync_reset(sync);
516 // Get the serial number of the stream we use
517 if(demuxer->video->id >= 0) {
518 sid = demuxer->video->id;
519 /* demux_ogg_read_packet needs decoder context for Theora streams */
520 if (((sh_video_t*)demuxer->video->sh)->format == FOURCC_THEORA)
521 context = ((sh_video_t*)demuxer->video->sh)->context;
523 else if(demuxer->audio->id >= 0) {
524 sid = demuxer->audio->id;
525 /* demux_ogg_read_packet needs decoder context for Vorbis streams */
526 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
527 context = ((sh_audio_t*)demuxer->audio->sh)->context;
528 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
531 else return;
532 os = &ogg_d->subs[sid];
533 oss = &os->stream;
535 while(1) {
536 np = ogg_sync_pageseek(sync,page);
537 if(np < 0) { // We had to skip some bytes
538 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
539 pos += -np;
540 continue;
542 if(np <= 0) { // We need more data
543 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
544 int len = stream_read(s,buf,BLOCK_SIZE);
545 if(len == 0 && s->eof)
546 break;
547 ogg_sync_wrote(sync,len);
548 continue;
550 // The page is ready
551 //ogg_sync_pageout(sync,page);
552 if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
553 pos += np;
554 continue;
556 if(ogg_stream_pagein(oss,page) != 0) {
557 mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
558 pos += np;
559 continue;
561 p = 0;
562 while(ogg_stream_packetout(oss,&op) == 1) {
563 float pts;
564 int flags;
565 demux_ogg_read_packet(os,&op,context,&pts,&flags,samplesize);
566 if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;
567 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
568 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
569 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
570 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
571 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
572 ogg_d->num_syncpoint++;
574 p++;
576 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
577 last_pos = pos;
578 pos += np;
579 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
581 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
583 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
584 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
586 stream_reset(s);
587 stream_seek(s,demuxer->movi_start);
588 ogg_sync_reset(sync);
589 for(np = 0 ; np < ogg_d->num_sub ; np++) {
590 ogg_stream_reset(&ogg_d->subs[np].stream);
591 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
595 // Get the first page
596 while(1) {
597 np = ogg_sync_pageout(sync,page);
598 if(np <= 0) { // We need more data
599 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
600 int len = stream_read(s,buf,BLOCK_SIZE);
601 if(len == 0 && s->eof) {
602 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
603 break;
606 ogg_sync_wrote(sync,len);
607 continue;
609 demux_ogg_get_page_stream(ogg_d,&oss);
610 ogg_stream_pagein(oss,page);
611 break;
616 extern void print_wave_header(WAVEFORMATEX *h, int verbose_level);
617 extern void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
619 /* defined in demux_mov.c */
620 extern unsigned int store_ughvlc(unsigned char *s, unsigned int v);
622 /** \brief Change the current subtitle stream and return its ID.
624 \param demuxer The demuxer whose subtitle stream will be changed.
625 \param new_num The number of the new subtitle track. The number must be
626 between 0 and ogg_d->n_text - 1.
628 \returns The Ogg stream number ( = page serial number) of the newly selected
629 track.
631 int demux_ogg_sub_id(demuxer_t *demuxer, int index) {
632 ogg_demuxer_t *ogg_d = demuxer->priv;
633 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
636 /** \brief Translate the ogg track number into the subtitle number.
637 * \param demuxer The demuxer about whose subtitles we are inquiring.
638 * \param id The ogg track number of the subtitle track.
640 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
641 ogg_demuxer_t *ogg_d = demuxer->priv;
642 int i;
643 for (i = 0; i < ogg_d->n_text; i++)
644 if (ogg_d->text_ids[i] == id) return i;
645 return -1;
648 /** \brief Lookup the subtitle language by the subtitle number. Returns NULL on out-of-bounds input.
649 * \param demuxer The demuxer about whose subtitles we are inquiring.
650 * \param index The subtitle number.
652 const char *demux_ogg_sub_lang(demuxer_t *demuxer, int index) {
653 ogg_demuxer_t *ogg_d = demuxer->priv;
654 return (index < 0) ? NULL : (index >= ogg_d->n_text) ? NULL : ogg_d->text_langs[index];
657 static void demux_close_ogg(demuxer_t* demuxer);
659 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
661 int i, offset;
662 int ris, init_error = 0;
663 ogg_packet op[3];
664 unsigned char *buf[3];
665 unsigned char *ptr;
666 unsigned int len;
667 ogg_stream_t *os = &od->subs[sh->ds->id];
668 vorbis_comment vc;
670 vorbis_info_init(&os->vi);
671 vorbis_comment_init(&vc);
672 for(i = 0; i < 3; i++) {
673 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
674 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
675 if(op[i].bytes < 0) {
676 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
677 return;
679 buf[i] = malloc(op[i].bytes);
680 if(!buf[i])
681 return;
682 memcpy(buf[i], op[i].packet, op[i].bytes);
684 op[i].b_o_s = (i==0);
685 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
686 if(ris < 0) {
687 init_error = 1;
688 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
691 vorbis_comment_clear(&vc);
692 if(!init_error)
693 os->vi_inited = 1;
695 len = op[0].bytes + op[1].bytes + op[2].bytes;
696 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
697 ptr = (unsigned char*) (sh->wf+1);
699 ptr[0] = 2;
700 offset = 1;
701 offset += store_ughvlc(&ptr[offset], op[0].bytes);
702 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
703 offset += store_ughvlc(&ptr[offset], op[1].bytes);
704 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
705 for(i = 0; i < 3; i++) {
706 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
707 memcpy(&ptr[offset], buf[i], op[i].bytes);
708 offset += op[i].bytes;
710 sh->wf->cbSize = offset;
711 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
712 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
714 if(op[0].bytes >= 29) {
715 unsigned int br;
716 int nombr, minbr, maxbr;
717 ptr = buf[0];
718 sh->channels = ptr[11];
719 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
720 maxbr = AV_RL32(&ptr[16]); //max
721 nombr = AV_RL32(&ptr[20]); //nominal
722 minbr = AV_RL32(&ptr[24]); //minimum
724 if(maxbr == -1)
725 maxbr = 0;
726 if(nombr == -1)
727 nombr = 0;
728 if(minbr == -1)
729 minbr = 0;
731 br = maxbr / 8;
732 if(!br)
733 br = nombr / 8;
734 if(!br)
735 br = minbr / 8;
736 sh->wf->nAvgBytesPerSec = br;
737 sh->wf->wBitsPerSample = 16;
738 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
740 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",
741 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
743 free(buf[2]);
744 free(buf[1]);
745 free(buf[0]);
749 /// Open an ogg physical stream
750 // Not static because it's used also in demuxer_avi.c
751 int demux_ogg_open(demuxer_t* demuxer) {
752 ogg_demuxer_t* ogg_d;
753 stream_t *s;
754 char* buf;
755 int np,s_no, n_audio = 0, n_video = 0;
756 int audio_id = -1, video_id = -1, text_id = -1;
757 ogg_sync_state* sync;
758 ogg_page* page;
759 ogg_packet pack;
760 sh_audio_t* sh_a;
761 sh_video_t* sh_v;
763 #ifdef USE_ICONV
764 subcp_open(NULL);
765 #endif
767 s = demuxer->stream;
769 demuxer->priv =
770 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
771 sync = &ogg_d->sync;
772 page = &ogg_d->page;
774 ogg_sync_init(sync);
776 while(1) {
777 /// Try to get a page
778 ogg_d->pos += ogg_d->last_size;
779 np = ogg_sync_pageseek(sync,page);
780 /// Error
781 if(np < 0) {
782 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
783 goto err_out;
785 /// Need some more data
786 if(np == 0) {
787 int len;
788 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
789 len = stream_read(s,buf,BLOCK_SIZE);
790 if(len == 0 && s->eof) {
791 goto err_out;
793 ogg_sync_wrote(sync,len);
794 continue;
796 ogg_d->last_size = np;
797 // We got one page now
799 if( ! ogg_page_bos(page) ) { // It's not a beginning page
800 // Header parsing end here, we need to get the page otherwise it will be lost
801 int id = demux_ogg_get_page_stream(ogg_d,NULL);
802 if(id >= 0)
803 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
804 else
805 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
806 break;
809 /// Init the data structure needed for a logical stream
810 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
811 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
812 /// Get the stream serial number
813 s_no = ogg_page_serialno(page);
814 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
815 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
816 // Take the first page
817 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
818 // Get first packet of the page
819 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
821 // Reset our vars
822 sh_a = NULL;
823 sh_v = NULL;
825 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
827 // Check for Vorbis
828 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
829 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
830 sh_a->format = FOURCC_VORBIS;
831 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
832 ogg_d->subs[ogg_d->num_sub].id = n_audio;
833 n_audio++;
834 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
835 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
836 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
837 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
838 sh_a->format = FOURCC_SPEEX;
839 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
840 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
841 sh_a->wf->wFormatTag = sh_a->format;
842 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
843 sh_a->wf->nBlockAlign = 0;
844 sh_a->wf->wBitsPerSample = 16;
845 sh_a->samplesize = 2;
846 sh_a->wf->cbSize = pack.bytes;
847 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
849 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
850 ogg_d->subs[ogg_d->num_sub].speex = 1;
851 ogg_d->subs[ogg_d->num_sub].id = n_audio;
852 n_audio++;
853 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
855 // check for Theora
856 # ifdef HAVE_OGGTHEORA
857 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
858 int errorCode = 0;
859 theora_info inf;
860 theora_comment cc;
862 theora_info_init (&inf);
863 theora_comment_init (&cc);
865 errorCode = theora_decode_header (&inf, &cc, &pack);
866 if (errorCode)
867 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
868 errorCode);
869 else
871 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
873 sh_v->context = NULL;
874 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
875 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
876 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
877 sh_v->fps = ((double)inf.fps_numerator)/
878 (double)inf.fps_denominator;
879 sh_v->frametime = ((double)inf.fps_denominator)/
880 (double)inf.fps_numerator;
881 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
882 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
883 sh_v->bih->biBitCount = 24;
884 sh_v->bih->biPlanes = 3;
885 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
886 sh_v->bih->biWidth*sh_v->bih->biHeight);
887 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
888 ogg_d->subs[ogg_d->num_sub].theora = 1;
889 ogg_d->subs[ogg_d->num_sub].id = n_video;
890 n_video++;
891 mp_msg(MSGT_DEMUX,MSGL_INFO,
892 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
893 ogg_d->num_sub,
894 (int)inf.version_major,
895 (int)inf.version_minor,
896 (int)inf.version_subminor,
897 n_video - 1);
898 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
900 theora_comment_clear(&cc);
901 theora_info_clear(&inf);
902 # endif /* HAVE_OGGTHEORA */
903 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
904 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
905 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
906 ogg_d->subs[ogg_d->num_sub].id = n_audio;
907 n_audio++;
908 ogg_d->subs[ogg_d->num_sub].flac = 1;
909 sh_a->wf = NULL;
910 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
911 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
912 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
913 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
914 ogg_d->subs[ogg_d->num_sub].id = n_audio;
915 n_audio++;
916 ogg_d->subs[ogg_d->num_sub].flac = 2;
917 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
918 sh_a->wf->wFormatTag = sh_a->format;
919 sh_a->wf->cbSize = 34;
920 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
921 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
923 /// Check for old header
924 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
926 // Old video header
927 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
928 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
929 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
930 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
931 sh_v->bih->biCompression=
932 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
933 pack.packet[70],pack.packet[71]);
934 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
935 sh_v->fps = 1/sh_v->frametime;
936 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
937 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
938 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
939 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
940 sh_v->bih->biPlanes=1;
941 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
943 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
944 ogg_d->subs[ogg_d->num_sub].id = n_video;
945 n_video++;
946 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
947 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
948 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
949 // Old audio header
950 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
951 unsigned int extra_size;
952 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
953 extra_size = AV_RL16(pack.packet+140);
954 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
955 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
956 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
957 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
958 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
959 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
960 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
961 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
962 sh_a->wf->cbSize = extra_size;
963 if(extra_size > 0)
964 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
966 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
967 ogg_d->subs[ogg_d->num_sub].id = n_audio;
968 n_audio++;
969 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);
970 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
971 } else
972 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
974 // Check new header
975 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
976 pack.bytes >= (int)sizeof(stream_header)+1) {
977 stream_header *st = (stream_header*)(pack.packet+1);
978 /// New video header
979 if(strncmp(st->streamtype,"video",5) == 0) {
980 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
981 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
982 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
983 sh_v->bih->biCompression=
984 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
985 st->subtype[2],st->subtype[3]);
986 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
987 sh_v->fps = 1.0/sh_v->frametime;
988 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
989 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
990 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
991 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
992 sh_v->bih->biPlanes=1;
993 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
995 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
996 ogg_d->subs[ogg_d->num_sub].id = n_video;
997 n_video++;
998 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
999 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
1000 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
1001 /// New audio header
1002 } else if(strncmp(st->streamtype,"audio",5) == 0) {
1003 char buffer[5];
1004 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1005 unsigned int extra_offset = 0;
1007 memcpy(buffer,st->subtype,4);
1008 buffer[4] = '\0';
1010 /* Nasty workaround. stream_header.size seems not to contain the real
1011 size in all cases. There are four extra bytes that are unaccounted
1012 for in front of the real codec initialization data _at least_ for
1013 AAC. So far I've only seen those bytes being all 0, so we can
1014 just skip them here. */
1015 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1016 extra_size -= 4;
1017 extra_offset = 4;
1020 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1021 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1022 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1023 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1024 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1025 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1026 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1027 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1028 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1029 sh_a->wf->cbSize = extra_size;
1030 if(extra_size)
1031 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1033 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1034 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1035 n_audio++;
1036 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);
1037 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1039 /// Check for text (subtitles) header
1040 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1041 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);
1042 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1043 ogg_d->subs[ogg_d->num_sub].text = 1;
1044 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1045 if (demuxer->sub->id == ogg_d->n_text)
1046 text_id = ogg_d->num_sub;
1047 new_sh_sub(demuxer, ogg_d->n_text);
1048 ogg_d->n_text++;
1049 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1050 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1051 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1052 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1053 //// Unknown header type
1054 } else
1055 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1056 /// Unknown (invalid ?) header
1057 } else
1058 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1060 if(sh_a || sh_v) {
1061 demux_stream_t* ds = NULL;
1062 if(sh_a) {
1063 // If the audio stream is not defined we took the first one
1064 if(demuxer->audio->id == -1) {
1065 demuxer->audio->id = n_audio - 1;
1066 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1068 /// Is it the stream we want
1069 if(demuxer->audio->id == n_audio - 1) {
1070 demuxer->audio->sh = sh_a;
1071 sh_a->ds = demuxer->audio;
1072 ds = demuxer->audio;
1073 audio_id = ogg_d->num_sub;
1076 if(sh_v) {
1077 /// Also for video
1078 if(demuxer->video->id == -1) {
1079 demuxer->video->id = n_video - 1;
1080 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1082 if(demuxer->video->id == n_video - 1) {
1083 demuxer->video->sh = sh_v;
1084 sh_v->ds = demuxer->video;
1085 ds = demuxer->video;
1086 video_id = ogg_d->num_sub;
1089 /// Add the header packets if the stream isn't seekable
1090 if(ds && !s->end_pos) {
1091 /// Finish the page, otherwise packets will be lost
1092 do {
1093 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1094 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1097 ogg_d->num_sub++;
1100 if(!n_video && !n_audio) {
1101 goto err_out;
1104 if(!n_video || video_id < 0)
1105 demuxer->video->id = -2;
1106 else
1107 demuxer->video->id = video_id;
1108 if(!n_audio || audio_id < 0)
1109 demuxer->audio->id = -2;
1110 else
1111 demuxer->audio->id = audio_id;
1112 /* Disable the subs only if there are no text streams at all.
1113 Otherwise the stream to display might be chosen later when the comment
1114 packet is encountered and the user used -slang instead of -sid. */
1115 if(!ogg_d->n_text)
1116 demuxer->sub->id = -2;
1117 else if (text_id >= 0) {
1118 demuxer->sub->id = text_id;
1119 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1122 ogg_d->final_granulepos=0;
1123 if(!s->end_pos)
1124 demuxer->seekable = 0;
1125 else {
1126 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1127 demuxer->movi_end = s->end_pos;
1128 demuxer->seekable = 1;
1129 demux_ogg_scan_stream(demuxer);
1132 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":"");
1134 sh_a = demuxer->audio->sh;
1135 if(sh_a)
1136 if(sh_a->format == FOURCC_VORBIS)
1137 fixup_vorbis_wf(sh_a, ogg_d);
1139 return DEMUXER_TYPE_OGG;
1141 err_out:
1142 return 0;
1146 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1147 ogg_demuxer_t* ogg_d;
1148 stream_t *s;
1149 demux_stream_t *ds;
1150 ogg_sync_state* sync;
1151 ogg_stream_state* os;
1152 ogg_page* page;
1153 ogg_packet pack;
1154 int np = 0, id=0;
1156 s = d->stream;
1157 ogg_d = d->priv;
1158 sync = &ogg_d->sync;
1159 page = &ogg_d->page;
1161 /// Find the stream we are working on
1162 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1163 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1164 return 0;
1167 while(1) {
1168 np = 0;
1169 ds = NULL;
1170 /// Try to get some packet from the current page
1171 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1172 /// No packet we go the next page
1173 if(np == 0) {
1174 while(1) {
1175 int pa,len;
1176 char *buf;
1177 ogg_d->pos += ogg_d->last_size;
1178 /// Get the next page from the physical stream
1179 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1180 /// Error : we skip some bytes
1181 if(pa < 0) {
1182 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1183 ogg_d->pos -= pa;
1184 continue;
1186 /// We need more data
1187 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1188 len = stream_read(s,buf,BLOCK_SIZE);
1189 if(len == 0 && s->eof) {
1190 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1191 return 0;
1193 ogg_sync_wrote(sync,len);
1194 } /// Page loop
1195 ogg_d->last_size = pa;
1196 /// Find the page's logical stream
1197 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1198 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1199 return 0;
1201 /// Take the page
1202 if(ogg_stream_pagein(os,page) == 0)
1203 break;
1204 /// Page was invalid => retry
1205 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1206 ogg_d->pos += ogg_d->last_size;
1208 } else /// Packet was corrupted
1209 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1210 } /// Packet loop
1212 /// Is the actual logical stream in use ?
1213 if(id == d->audio->id)
1214 ds = d->audio;
1215 else if(id == d->video->id)
1216 ds = d->video;
1217 else if (ogg_d->subs[id].text)
1218 ds = d->sub;
1220 if(ds) {
1221 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1222 continue; /// Unuseful packet, get another
1223 d->filepos = ogg_d->pos;
1224 return 1;
1227 } /// while(1)
1231 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1232 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1233 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1234 demuxer_t *od;
1235 ogg_demuxer_t *ogg_d;
1236 stream_t* s;
1237 uint32_t hdrsizes[3];
1238 demux_packet_t *dp;
1239 sh_audio_t *sh_audio = demuxer->audio->sh;
1240 int np;
1241 uint8_t *extradata = sh_audio->wf + 1;
1242 int i;
1243 unsigned char *p = NULL,*buf;
1244 int plen;
1246 /// Check that the cbSize is big enough for the following reads
1247 if(sh_audio->wf->cbSize < 22+3*4) {
1248 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1249 goto fallback;
1251 /// Get the size of the 3 header packet
1252 extradata += 22;
1253 for (i = 0; i < 3; i++) {
1254 hdrsizes[i] = AV_RL32(extradata);
1255 extradata += 4;
1257 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1259 /// Check the size
1260 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1261 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1262 goto fallback;
1265 // Build the ogg demuxer private datas
1266 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1267 ogg_d->num_sub = 1;
1268 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1269 ogg_d->subs[0].vorbis = 1;
1271 // Init the ogg physical stream
1272 ogg_sync_init(&ogg_d->sync);
1274 // Get the first page of the stream : we assume there only 1 logical stream
1275 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1276 if(np < 0) {
1277 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1278 free(ogg_d);
1279 goto fallback;
1281 // Add some data
1282 plen = ds_get_packet(demuxer->audio,&p);
1283 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1284 memcpy(buf,p,plen);
1285 ogg_sync_wrote(&ogg_d->sync,plen);
1287 // Init the logical stream
1288 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1289 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1290 // Write the page
1291 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1293 // Create the ds_stream and the ogg demuxer
1294 s = new_ds_stream(demuxer->audio);
1295 od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1297 /// Add the header packets in the ogg demuxer audio stream
1298 for (i = 0; i < 3; i++) {
1299 dp = new_demux_packet(hdrsizes[i]);
1300 memcpy(dp->buffer,extradata,hdrsizes[i]);
1301 ds_add_packet(od->audio,dp);
1302 extradata += hdrsizes[i];
1305 // Finish setting up the ogg demuxer
1306 od->priv = ogg_d;
1307 sh_audio = new_sh_audio(od,0);
1308 od->audio->id = 0;
1309 od->video->id = -2;
1310 od->audio->sh = sh_audio;
1311 sh_audio->ds = od->audio;
1312 sh_audio->format = FOURCC_VORBIS;
1313 fixup_vorbis_wf(sh_audio, ogg_d);
1315 /// Return the joined demuxers
1316 return new_demuxers_demuxer(demuxer,od,demuxer);
1318 fallback:
1319 demuxer->audio->id = -2;
1320 return demuxer;
1324 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1325 ogg_demuxer_t* ogg_d = demuxer->priv;
1326 ogg_sync_state* sync = &ogg_d->sync;
1327 ogg_page* page= &ogg_d->page;
1328 ogg_stream_state* oss;
1329 ogg_stream_t* os;
1330 demux_stream_t* ds;
1331 ogg_packet op;
1332 float rate;
1333 int i,sp,first,precision=1,do_seek=1;
1334 vorbis_info* vi = NULL;
1335 int64_t gp = 0, old_gp;
1336 void *context = NULL;
1337 off_t pos, old_pos;
1338 int np;
1339 int is_gp_valid;
1340 float pts;
1341 int is_keyframe;
1342 int samplesize=1;
1343 ogg_int64_t granulepos_orig;
1345 if(demuxer->video->id >= 0) {
1346 ds = demuxer->video;
1347 /* demux_ogg_read_packet needs decoder context for Theora streams */
1348 if (((sh_video_t*)demuxer->video->sh)->format == FOURCC_THEORA)
1349 context = ((sh_video_t*)demuxer->video->sh)->context;
1350 rate = ogg_d->subs[ds->id].samplerate;
1351 } else {
1352 ds = demuxer->audio;
1353 os = &ogg_d->subs[ds->id];
1354 /* demux_ogg_read_packet needs decoder context for Vorbis streams */
1355 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS)
1356 context = ((sh_audio_t*)demuxer->audio->sh)->context;
1357 vi = &(os->vi);
1358 rate = (float)vi->rate;
1359 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1362 os = &ogg_d->subs[ds->id];
1363 oss = &os->stream;
1365 old_gp = os->lastpos;
1366 old_pos = ogg_d->pos;
1368 //calculate the granulepos to seek to
1369 gp = flags & 1 ? 0 : os->lastpos;
1370 if(flags & 2) {
1371 if (ogg_d->final_granulepos > 0)
1372 gp += ogg_d->final_granulepos * rel_seek_secs;
1373 else
1374 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1375 } else
1376 gp += rel_seek_secs * rate;
1377 if (gp < 0) gp = 0;
1379 //calculate the filepos to seek to
1380 if(ogg_d->syncpoints) {
1381 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1382 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1385 if(sp >= ogg_d->num_syncpoint) return;
1386 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1387 sp--;
1388 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1389 if (sp > 0 && gp < os->lastpos) sp--;
1390 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1392 pos = ogg_d->syncpoints[sp].page_pos;
1393 precision = 0;
1394 } else {
1395 pos = flags & 1 ? 0 : ogg_d->pos;
1396 if(flags & 2)
1397 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1398 else {
1399 if (ogg_d->final_granulepos > 0) {
1400 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);
1401 } else if (os->lastpos > 0) {
1402 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1405 if (pos < 0) pos = 0;
1406 if (pos > (demuxer->movi_end - demuxer->movi_start))
1407 pos = demuxer->movi_end - demuxer->movi_start;
1408 } // if(ogg_d->syncpoints)
1410 while(1) {
1411 if (do_seek) {
1412 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1413 ogg_sync_reset(sync);
1414 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1415 ogg_stream_reset(&ogg_d->subs[i].stream);
1416 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1418 ogg_d->pos = pos;
1419 ogg_d->last_size = 0;
1420 /* we just guess that we reached correct granulepos, in case a
1421 subsequent search occurs before we read a valid granulepos */
1422 os->lastpos = gp;
1423 first = !(ogg_d->syncpoints);
1424 do_seek=0;
1426 ogg_d->pos += ogg_d->last_size;
1427 ogg_d->last_size = 0;
1428 np = ogg_sync_pageseek(sync,page);
1430 if(np < 0)
1431 ogg_d->pos -= np;
1432 if(np <= 0) { // We need more data
1433 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1434 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1435 if(len == 0 && demuxer->stream->eof) {
1436 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1437 return;
1439 ogg_sync_wrote(sync,len);
1440 continue;
1442 ogg_d->last_size = np;
1443 if(ogg_page_serialno(page) != oss->serialno)
1444 continue;
1446 if(ogg_stream_pagein(oss,page) != 0)
1447 continue;
1449 while(1) {
1450 np = ogg_stream_packetout(oss,&op);
1451 if(np < 0)
1452 continue;
1453 else if(np == 0)
1454 break;
1455 if (first) { /* Discard the first packet as it's probably broken,
1456 and we don't have any other means to decide whether it is
1457 complete or not. */
1458 first = 0;
1459 break;
1461 is_gp_valid = (op.granulepos >= 0);
1462 granulepos_orig=op.granulepos;
1463 demux_ogg_read_packet(os,&op,context,&pts,&is_keyframe,samplesize);
1464 if (precision && is_gp_valid) {
1465 precision--;
1466 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1467 //prepare another seek because we are off by more than 1s
1468 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1469 if (pos < 0) pos = 0;
1470 if (pos < demuxer->movi_end - demuxer->movi_start) {
1471 do_seek=1;
1472 break;
1476 if (is_gp_valid && pos > 0 && old_gp > gp
1477 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1478 /* prepare another seek because looking for a syncpoint
1479 destroyed the backward search */
1480 pos = old_pos - 1.5 * (old_pos - pos);
1481 if (pos < 0) pos = 0;
1482 if (pos < demuxer->movi_end - demuxer->movi_start) {
1483 do_seek=1;
1484 break;
1487 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1488 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1489 vo_sub = &ogg_sub;
1490 vo_osd_changed(OSDTYPE_SUBTITLE);
1492 op.granulepos=granulepos_orig;
1493 demux_ogg_add_packet(ds,os,ds->id,&op);
1494 return;
1499 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1503 static void demux_close_ogg(demuxer_t* demuxer) {
1504 ogg_demuxer_t* ogg_d = demuxer->priv;
1505 ogg_stream_t* os = NULL;
1506 int i;
1508 if(!ogg_d)
1509 return;
1511 #ifdef USE_ICONV
1512 subcp_close();
1513 #endif
1515 ogg_sync_clear(&ogg_d->sync);
1516 if(ogg_d->subs)
1518 for (i = 0; i < ogg_d->num_sub; i++)
1520 os = &ogg_d->subs[i];
1521 ogg_stream_clear(&os->stream);
1522 if(os->vi_inited)
1523 vorbis_info_clear(&os->vi);
1525 free(ogg_d->subs);
1527 if(ogg_d->syncpoints)
1528 free(ogg_d->syncpoints);
1529 if (ogg_d->text_ids)
1530 free(ogg_d->text_ids);
1531 if (ogg_d->text_langs) {
1532 for (i = 0; i < ogg_d->n_text; i++)
1533 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1534 free(ogg_d->text_langs);
1536 free(ogg_d);
1539 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1540 ogg_demuxer_t* ogg_d = demuxer->priv;
1541 ogg_stream_t* os;
1542 float rate;
1544 if(demuxer->video->id >= 0) {
1545 os = &ogg_d->subs[demuxer->video->id];
1546 rate = os->samplerate;
1547 } else {
1548 os = &ogg_d->subs[demuxer->audio->id];
1549 rate = os->vi.rate;
1553 switch(cmd) {
1554 case DEMUXER_CTRL_GET_TIME_LENGTH:
1555 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1556 *(double *)arg=(double)ogg_d->final_granulepos / rate;
1557 return DEMUXER_CTRL_GUESS;
1559 case DEMUXER_CTRL_GET_PERCENT_POS:
1560 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1561 *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos;
1562 return DEMUXER_CTRL_OK;
1564 default:
1565 return DEMUXER_CTRL_NOTIMPL;
1571 demuxer_desc_t demuxer_desc_ogg = {
1572 "Ogg demuxer",
1573 "ogg",
1574 "Ogg",
1575 "?",
1577 DEMUXER_TYPE_OGG,
1578 1, // safe autodetect
1579 demux_ogg_open,
1580 demux_ogg_fill_buffer,
1581 NULL,
1582 demux_close_ogg,
1583 demux_ogg_seek,
1584 demux_ogg_control