Get rid of completely pointless vt_doit variable
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blob2667b4ce1b53b401e344aa62ae4d1ce5af662324
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "config.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <math.h>
26 #include <inttypes.h>
28 #include "mp_msg.h"
29 #include "help_mp.h"
30 #include "stream/stream.h"
31 #include "demuxer.h"
32 #include "stheader.h"
33 #include "libavutil/intreadwrite.h"
35 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
36 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
37 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
39 #ifdef CONFIG_TREMOR
40 #include <tremor/ogg.h>
41 #include <tremor/ivorbiscodec.h>
42 #else
43 #include <ogg/ogg.h>
44 #include <vorbis/codec.h>
45 #endif
47 #ifdef CONFIG_OGGTHEORA
48 #include <theora/theora.h>
49 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
50 #endif
52 #define BLOCK_SIZE 4096
54 /* Theora decoder context : we won't be able to interpret granule positions
55 * without using theora_granule_time with the theora_state of the stream.
56 * This is duplicated in `vd_theora.c'; put this in a common header?
58 #ifdef CONFIG_OGGTHEORA
59 typedef struct theora_struct_st {
60 theora_state st;
61 theora_comment cc;
62 theora_info inf;
63 } theora_struct_t;
64 #endif
66 //// OggDS headers
67 // Header for the new header format
68 typedef struct stream_header_video
70 ogg_int32_t width;
71 ogg_int32_t height;
72 } stream_header_video;
74 typedef struct stream_header_audio
76 ogg_int16_t channels;
77 ogg_int16_t blockalign;
78 ogg_int32_t avgbytespersec;
79 } stream_header_audio;
81 typedef struct __attribute__((__packed__)) stream_header
83 char streamtype[8];
84 char subtype[4];
86 ogg_int32_t size; // size of the structure
88 ogg_int64_t time_unit; // in reference time
89 ogg_int64_t samples_per_unit;
90 ogg_int32_t default_len; // in media time
92 ogg_int32_t buffersize;
93 ogg_int16_t bits_per_sample;
95 ogg_int16_t padding;
97 union
99 // Video specific
100 stream_header_video video;
101 // Audio specific
102 stream_header_audio audio;
103 } sh;
104 } stream_header;
106 /// Our private datas
108 typedef struct ogg_syncpoint {
109 int64_t granulepos;
110 off_t page_pos;
111 } ogg_syncpoint_t;
113 /// A logical stream
114 typedef struct ogg_stream {
115 /// Timestamping stuff
116 float samplerate; /// granulpos 2 time
117 int64_t lastpos;
118 int32_t lastsize;
119 int keyframe_frequency_force;
121 // Logical stream state
122 ogg_stream_state stream;
123 int hdr_packets;
124 int vorbis;
125 int speex;
126 int theora;
127 int flac;
128 int text;
129 int id;
131 vorbis_info vi;
132 int vi_initialized;
134 void *ogg_d;
135 } ogg_stream_t;
137 typedef struct ogg_demuxer {
138 /// Physical stream state
139 ogg_sync_state sync;
140 /// Current page
141 ogg_page page;
142 /// Logical streams
143 ogg_stream_t *subs;
144 int num_sub;
145 ogg_syncpoint_t* syncpoints;
146 int num_syncpoint;
147 off_t pos, last_size;
148 int64_t final_granulepos;
150 /* Used for subtitle switching. */
151 int n_text;
152 int *text_ids;
153 char **text_langs;
154 } ogg_demuxer_t;
156 #define NUM_VORBIS_HDR_PACKETS 3
158 /// Some defines from OggDS
159 #define PACKET_TYPE_HEADER 0x01
160 #define PACKET_TYPE_BITS 0x07
161 #define PACKET_LEN_BITS01 0xc0
162 #define PACKET_LEN_BITS2 0x02
163 #define PACKET_IS_SYNCPOINT 0x08
165 extern char *dvdsub_lang, *audio_lang;
166 extern int dvdsub_id;
168 //-------- subtitle support - should be moved to decoder layer, and queue
169 // - subtitles up in demuxer buffer...
171 #include "subreader.h"
172 #include "libvo/sub.h"
173 #define OGG_SUB_MAX_LINE 128
175 static subtitle ogg_sub;
176 //FILE* subout;
178 void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) {
179 int lcv;
180 char *packet = pack->packet;
182 if (pack->bytes < 4)
183 return;
184 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
185 (unsigned char)packet[0],
186 (unsigned char)packet[1],
187 (unsigned char)packet[2],
188 &packet[3]);
190 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
191 // Find data start
192 double endpts = MP_NOPTS_VALUE;
193 int32_t duration = 0;
194 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
195 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
196 lcv = 1 + hdrlen;
197 if (pack->bytes < lcv)
198 return;
199 for (i = hdrlen; i > 0; i--) {
200 duration <<= 8;
201 duration |= (unsigned char)packet[i];
203 if (hdrlen > 0 && duration > 0) {
204 float pts;
205 if(pack->granulepos == -1)
206 pack->granulepos = os->lastpos + os->lastsize;
207 pts = (float)pack->granulepos/(float)os->samplerate;
208 endpts = 1.0 + pts + (float)duration/1000.0;
210 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
211 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
214 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
215 ogg_sub.lines, ogg_sub.text[0]);
216 #ifdef CONFIG_ICONV
217 subcp_recode(&ogg_sub);
218 #endif
219 vo_sub = &ogg_sub;
220 vo_osd_changed(OSDTYPE_SUBTITLE);
224 // get the logical stream of the current page
225 // fill os if non NULL and return the stream id
226 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
227 int id,s_no;
228 ogg_page* page = &ogg_d->page;
230 s_no = ogg_page_serialno(page);
232 for(id= 0; id < ogg_d->num_sub ; id++) {
233 if(s_no == ogg_d->subs[id].stream.serialno)
234 break;
237 if(id == ogg_d->num_sub) {
238 // If we have only one vorbis stream allow the stream id to change
239 // it's normal on radio stream (each song have an different id).
240 // But we (or the codec?) should check that the samplerate, etc
241 // doesn't change (for radio stream it's ok)
242 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
243 ogg_stream_reset(&ogg_d->subs[0].stream);
244 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
245 id = 0;
246 } else
247 return -1;
250 if(os)
251 *os = &ogg_d->subs[id].stream;
253 return id;
257 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
258 unsigned char* data = pack->packet;
260 *pts = 0;
261 *flags = 0;
263 if(os->vorbis) {
264 if(*pack->packet & PACKET_TYPE_HEADER)
265 os->hdr_packets++;
266 else if (os->vi_initialized)
268 vorbis_info *vi;
269 int32_t blocksize;
271 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
272 vi = &(os->vi);
273 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
274 // Calculate the timestamp if the packet don't have any
275 if(pack->granulepos == -1) {
276 pack->granulepos = os->lastpos;
277 if(os->lastsize > 0)
278 pack->granulepos += os->lastsize;
280 *pts = pack->granulepos / (float)vi->rate;
281 os->lastsize = blocksize;
282 os->lastpos = pack->granulepos;
284 } else if (os->speex) {
285 // whole packet (default)
286 # ifdef CONFIG_OGGTHEORA
287 } else if (os->theora) {
288 /* we pass complete packets to theora, mustn't strip the header! */
289 os->lastsize = 1;
291 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
292 have theora_state st, until all header packets were passed to the
293 decoder. */
294 if (!(*data&0x80))
296 int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
297 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
299 if (pack->granulepos >= 0)
301 os->lastpos = pack->granulepos >> keyframe_granule_shift;
302 os->lastpos += pack->granulepos & iframemask;
303 *flags = (pack->granulepos & iframemask) == 0;
305 else
307 os->lastpos++;
309 pack->granulepos = os->lastpos;
310 *pts = (double)os->lastpos / (double)os->samplerate;
312 #endif /* CONFIG_OGGTHEORA */
313 } else if (os->flac) {
314 /* we pass complete packets to flac, mustn't strip the header! */
315 if (os->flac == 2 && pack->packet[0] != 0xff)
316 return NULL;
317 } else {
318 if(*pack->packet & PACKET_TYPE_HEADER)
319 os->hdr_packets++;
320 else {
321 // Find data start
322 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
323 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
324 data = pack->packet + 1 + hdrlen;
325 // Calculate the timestamp
326 if(pack->granulepos == -1)
327 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
328 // If we already have a timestamp it can be a syncpoint
329 if(*pack->packet & PACKET_IS_SYNCPOINT)
330 *flags = 1;
331 *pts = pack->granulepos/os->samplerate;
332 // Save the packet length and timestamp
333 os->lastsize = 0;
334 while(hdrlen) {
335 os->lastsize <<= 8;
336 os->lastsize |= pack->packet[hdrlen];
337 hdrlen--;
339 os->lastpos = pack->granulepos;
342 return data;
345 // check if clang has substring from comma separated langlist
346 static int demux_ogg_check_lang(const char *clang, const char *langlist)
348 const char *c;
350 if (!langlist || !*langlist)
351 return 0;
352 while ((c = strchr(langlist, ',')))
354 if (!strncasecmp(clang, langlist, c - langlist))
355 return 1;
356 langlist = &c[1];
358 if (!strncasecmp(clang, langlist, strlen(langlist)))
359 return 1;
360 return 0;
363 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id);
365 /// Try to print out comments and also check for LANGUAGE= tag
366 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
368 const char *hdr, *val;
369 char **cmt = vc->user_comments;
370 int index, i;
371 ogg_demuxer_t *ogg_d = d->priv;
372 static const struct table {
373 const char *ogg;
374 const char *mp;
375 } table[] = {
376 { "ENCODED_USING", "Software" },
377 { "ENCODER_URL", "Encoder URL" },
378 { "TITLE", "Title" },
379 { "ARTIST", "Artist" },
380 { "COMMENT", "Comments" },
381 { "DATE", "Creation Date" },
382 { "GENRE", "Genre" },
383 { "ALBUM", "Album" },
384 { "TRACKNUMBER", "Track" },
385 { NULL, NULL },
388 while(*cmt)
390 hdr = NULL;
391 if (!strncasecmp(*cmt, "LANGUAGE=", 9))
393 val = *cmt + 9;
394 if (ogg_d->subs[id].text)
395 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
396 else if (id != d->video->id)
397 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
398 if (ogg_d->subs[id].text)
399 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
400 // copy this language name into the array
401 index = demux_ogg_sub_reverse_id(d, id);
402 if (index >= 0) {
403 sh_sub_t* sh;
404 // in case of malicious files with more than one lang per track:
405 if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
406 ogg_d->text_langs[index] = strdup(val);
407 sh = d->s_streams[index];
408 if (sh && sh->lang) free(sh->lang);
409 if (sh) sh->lang = strdup(val);
411 // check for -slang if subs are uninitialized yet
412 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
414 d->sub->id = index;
415 dvdsub_id = index;
416 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
418 else
419 hdr = "Language";
421 else {
422 for (i = 0; table[i].ogg; i++)
424 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
425 (*cmt)[strlen(table[i].ogg)] == '=')
427 hdr = table[i].mp;
428 val = *cmt + strlen(table[i].ogg) + 1;
432 if (hdr)
433 demux_info_add(d, hdr, val);
434 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
435 cmt++;
439 /// Calculate the timestamp and add the packet to the demux stream
440 // return 1 if the packet was added, 0 otherwise
441 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
442 demuxer_t* d = ds->demuxer;
443 demux_packet_t* dp;
444 unsigned char* data;
445 float pts = 0;
446 int flags = 0;
447 int samplesize = 1;
449 // If packet is an comment header then we try to get comments at first
450 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
452 vorbis_info vi;
453 vorbis_comment vc;
455 vorbis_info_init(&vi);
456 vorbis_comment_init(&vc);
457 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
458 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
459 demux_ogg_check_comments(d, os, id, &vc);
460 vorbis_comment_clear(&vc);
461 vorbis_info_clear(&vi);
463 if (os->text) {
464 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
465 demux_ogg_add_sub(os,pack);
466 return 0;
468 if (os->speex) {
469 // discard first two packets, they contain the header and comment
470 if (os->hdr_packets < 2) {
471 os->hdr_packets++;
472 return 0;
474 } else
475 // If packet is an header we jump it except for vorbis and theora
476 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
477 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
478 // handled differently for each and every stream type. The joy! The joy!
479 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
480 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
481 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
482 return 0;
484 // For vorbis packet the packet is the data, for other codec we must jump
485 // the header
486 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
487 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
489 data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
490 if (!data)
491 return 0;
493 /// Clear subtitles if necessary (for broken files)
494 if (sub_clear_text(&ogg_sub, pts)) {
495 vo_sub = &ogg_sub;
496 vo_osd_changed(OSDTYPE_SUBTITLE);
498 /// Send the packet
499 dp = new_demux_packet(pack->bytes-(data-pack->packet));
500 memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
501 dp->pts = pts;
502 dp->flags = flags;
503 ds_add_packet(ds,dp);
504 mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
505 dp, ds, pts, dp->len, flags);
506 return 1;
509 /// if -forceidx build a table of all syncpoints to make seeking easier
510 /// otherwise try to get at least the final_granulepos
511 void demux_ogg_scan_stream(demuxer_t* demuxer) {
512 ogg_demuxer_t* ogg_d = demuxer->priv;
513 stream_t *s = demuxer->stream;
514 ogg_sync_state* sync = &ogg_d->sync;
515 ogg_page* page= &ogg_d->page;
516 ogg_stream_state* oss;
517 ogg_stream_t* os;
518 ogg_packet op;
519 int np,sid,p,samplesize=1;
520 off_t pos, last_pos;
521 pos = last_pos = demuxer->movi_start;
523 // Reset the stream
524 if(index_mode == 2) {
525 stream_seek(s,demuxer->movi_start);
526 } else {
527 //the 270000 are just a wild guess
528 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
530 ogg_sync_reset(sync);
532 // Get the serial number of the stream we use
533 if(demuxer->video->id >= 0) {
534 sid = demuxer->video->id;
536 else if(demuxer->audio->id >= 0) {
537 sid = demuxer->audio->id;
538 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
539 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
542 else return;
543 os = &ogg_d->subs[sid];
544 oss = &os->stream;
546 while(1) {
547 np = ogg_sync_pageseek(sync,page);
548 if(np < 0) { // We had to skip some bytes
549 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
550 pos += -np;
551 continue;
553 if(np <= 0) { // We need more data
554 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
555 int len = stream_read(s,buf,BLOCK_SIZE);
556 if(len == 0 && s->eof)
557 break;
558 ogg_sync_wrote(sync,len);
559 continue;
561 // The page is ready
562 //ogg_sync_pageout(sync,page);
563 if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
564 pos += np;
565 continue;
567 if(ogg_stream_pagein(oss,page) != 0) {
568 mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
569 pos += np;
570 continue;
572 p = 0;
573 while(ogg_stream_packetout(oss,&op) == 1) {
574 float pts;
575 int flags;
576 demux_ogg_read_packet(os,&op,&pts,&flags,samplesize);
577 if(op.granulepos >= 0) ogg_d->final_granulepos = op.granulepos;
578 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
579 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
580 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
581 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
582 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
583 ogg_d->num_syncpoint++;
585 p++;
587 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
588 last_pos = pos;
589 pos += np;
590 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
592 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
594 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
595 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
597 stream_reset(s);
598 stream_seek(s,demuxer->movi_start);
599 ogg_sync_reset(sync);
600 for(np = 0 ; np < ogg_d->num_sub ; np++) {
601 ogg_stream_reset(&ogg_d->subs[np].stream);
602 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
606 // Get the first page
607 while(1) {
608 np = ogg_sync_pageout(sync,page);
609 if(np <= 0) { // We need more data
610 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
611 int len = stream_read(s,buf,BLOCK_SIZE);
612 if(len == 0 && s->eof) {
613 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
614 break;
617 ogg_sync_wrote(sync,len);
618 continue;
620 demux_ogg_get_page_stream(ogg_d,&oss);
621 ogg_stream_pagein(oss,page);
622 break;
627 void print_wave_header(WAVEFORMATEX *h, int verbose_level);
628 void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
630 /* defined in demux_mov.c */
631 unsigned int store_ughvlc(unsigned char *s, unsigned int v);
633 /** \brief Change the current subtitle stream and return its ID.
635 \param demuxer The demuxer whose subtitle stream will be changed.
636 \param new_num The number of the new subtitle track. The number must be
637 between 0 and ogg_d->n_text - 1.
639 \returns The Ogg stream number ( = page serial number) of the newly selected
640 track.
642 int demux_ogg_sub_id(demuxer_t *demuxer, int index) {
643 ogg_demuxer_t *ogg_d = demuxer->priv;
644 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
647 /** \brief Translate the ogg track number into the subtitle number.
648 * \param demuxer The demuxer about whose subtitles we are inquiring.
649 * \param id The ogg track number of the subtitle track.
651 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
652 ogg_demuxer_t *ogg_d = demuxer->priv;
653 int i;
654 for (i = 0; i < ogg_d->n_text; i++)
655 if (ogg_d->text_ids[i] == id) return i;
656 return -1;
659 static void demux_close_ogg(demuxer_t* demuxer);
661 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
663 int i, offset;
664 int ris, init_error = 0;
665 ogg_packet op[3];
666 unsigned char *buf[3];
667 unsigned char *ptr;
668 unsigned int len;
669 ogg_stream_t *os = &od->subs[sh->ds->id];
670 vorbis_comment vc;
672 vorbis_info_init(&os->vi);
673 vorbis_comment_init(&vc);
674 for(i = 0; i < 3; i++) {
675 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
676 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
677 if(op[i].bytes < 0) {
678 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
679 return;
681 buf[i] = malloc(op[i].bytes);
682 if(!buf[i])
683 return;
684 memcpy(buf[i], op[i].packet, op[i].bytes);
686 op[i].b_o_s = (i==0);
687 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
688 if(ris < 0) {
689 init_error = 1;
690 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
693 vorbis_comment_clear(&vc);
694 if(!init_error)
695 os->vi_initialized = 1;
697 len = op[0].bytes + op[1].bytes + op[2].bytes;
698 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
699 ptr = (unsigned char*) (sh->wf+1);
701 ptr[0] = 2;
702 offset = 1;
703 offset += store_ughvlc(&ptr[offset], op[0].bytes);
704 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
705 offset += store_ughvlc(&ptr[offset], op[1].bytes);
706 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
707 for(i = 0; i < 3; i++) {
708 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
709 memcpy(&ptr[offset], buf[i], op[i].bytes);
710 offset += op[i].bytes;
712 sh->wf->cbSize = offset;
713 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
714 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
716 if(op[0].bytes >= 29) {
717 unsigned int br;
718 int nombr, minbr, maxbr;
719 ptr = buf[0];
720 sh->channels = ptr[11];
721 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
722 maxbr = AV_RL32(&ptr[16]); //max
723 nombr = AV_RL32(&ptr[20]); //nominal
724 minbr = AV_RL32(&ptr[24]); //minimum
726 if(maxbr == -1)
727 maxbr = 0;
728 if(nombr == -1)
729 nombr = 0;
730 if(minbr == -1)
731 minbr = 0;
733 br = maxbr / 8;
734 if(!br)
735 br = nombr / 8;
736 if(!br)
737 br = minbr / 8;
738 sh->wf->nAvgBytesPerSec = br;
739 sh->wf->wBitsPerSample = 16;
740 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
742 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",
743 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
745 free(buf[2]);
746 free(buf[1]);
747 free(buf[0]);
751 /// Open an ogg physical stream
752 // Not static because it's used also in demuxer_avi.c
753 int demux_ogg_open(demuxer_t* demuxer) {
754 ogg_demuxer_t* ogg_d;
755 stream_t *s;
756 char* buf;
757 int np,s_no, n_audio = 0, n_video = 0;
758 int audio_id = -1, video_id = -1, text_id = -1;
759 ogg_sync_state* sync;
760 ogg_page* page;
761 ogg_packet pack;
762 sh_audio_t* sh_a;
763 sh_video_t* sh_v;
765 #ifdef CONFIG_ICONV
766 subcp_open(NULL);
767 #endif
769 s = demuxer->stream;
771 demuxer->priv =
772 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
773 sync = &ogg_d->sync;
774 page = &ogg_d->page;
776 ogg_sync_init(sync);
778 while(1) {
779 /// Try to get a page
780 ogg_d->pos += ogg_d->last_size;
781 np = ogg_sync_pageseek(sync,page);
782 /// Error
783 if(np < 0) {
784 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
785 goto err_out;
787 /// Need some more data
788 if(np == 0) {
789 int len;
790 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
791 len = stream_read(s,buf,BLOCK_SIZE);
792 if(len == 0 && s->eof) {
793 goto err_out;
795 ogg_sync_wrote(sync,len);
796 continue;
798 ogg_d->last_size = np;
799 // We got one page now
801 if( ! ogg_page_bos(page) ) { // It's not a beginning page
802 // Header parsing end here, we need to get the page otherwise it will be lost
803 int id = demux_ogg_get_page_stream(ogg_d,NULL);
804 if(id >= 0)
805 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
806 else
807 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
808 break;
811 /// Init the data structure needed for a logical stream
812 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
813 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
814 /// Get the stream serial number
815 s_no = ogg_page_serialno(page);
816 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
817 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
818 // Take the first page
819 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
820 // Get first packet of the page
821 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
823 // Reset our vars
824 sh_a = NULL;
825 sh_v = NULL;
827 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
829 // Check for Vorbis
830 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
831 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
832 sh_a->format = FOURCC_VORBIS;
833 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
834 ogg_d->subs[ogg_d->num_sub].id = n_audio;
835 n_audio++;
836 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
837 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
838 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
839 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
840 sh_a->format = FOURCC_SPEEX;
841 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
842 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
843 sh_a->wf->wFormatTag = sh_a->format;
844 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
845 sh_a->wf->nBlockAlign = 0;
846 sh_a->wf->wBitsPerSample = 16;
847 sh_a->samplesize = 2;
848 sh_a->wf->cbSize = pack.bytes;
849 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
851 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
852 ogg_d->subs[ogg_d->num_sub].speex = 1;
853 ogg_d->subs[ogg_d->num_sub].id = n_audio;
854 n_audio++;
855 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
857 // check for Theora
858 # ifdef CONFIG_OGGTHEORA
859 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
860 int errorCode = 0;
861 theora_info inf;
862 theora_comment cc;
864 theora_info_init (&inf);
865 theora_comment_init (&cc);
867 errorCode = theora_decode_header (&inf, &cc, &pack);
868 if (errorCode)
869 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
870 errorCode);
871 else
873 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
875 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
876 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
877 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
878 sh_v->fps = ((double)inf.fps_numerator)/
879 (double)inf.fps_denominator;
880 sh_v->frametime = ((double)inf.fps_denominator)/
881 (double)inf.fps_numerator;
882 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
883 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
884 sh_v->bih->biBitCount = 24;
885 sh_v->bih->biPlanes = 3;
886 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
887 sh_v->bih->biWidth*sh_v->bih->biHeight);
888 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
889 ogg_d->subs[ogg_d->num_sub].theora = 1;
890 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
891 ogg_d->subs[ogg_d->num_sub].id = n_video;
892 n_video++;
893 mp_msg(MSGT_DEMUX,MSGL_INFO,
894 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
895 ogg_d->num_sub,
896 (int)inf.version_major,
897 (int)inf.version_minor,
898 (int)inf.version_subminor,
899 n_video - 1);
900 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
902 theora_comment_clear(&cc);
903 theora_info_clear(&inf);
904 # endif /* CONFIG_OGGTHEORA */
905 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
906 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
907 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
908 ogg_d->subs[ogg_d->num_sub].id = n_audio;
909 n_audio++;
910 ogg_d->subs[ogg_d->num_sub].flac = 1;
911 sh_a->wf = NULL;
912 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
913 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
914 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
915 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
916 ogg_d->subs[ogg_d->num_sub].id = n_audio;
917 n_audio++;
918 ogg_d->subs[ogg_d->num_sub].flac = 2;
919 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
920 sh_a->wf->wFormatTag = sh_a->format;
921 sh_a->wf->cbSize = 34;
922 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
923 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
925 /// Check for old header
926 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
928 // Old video header
929 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
930 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
931 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
932 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
933 sh_v->bih->biCompression=
934 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
935 pack.packet[70],pack.packet[71]);
936 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
937 sh_v->fps = 1/sh_v->frametime;
938 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
939 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
940 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
941 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
942 sh_v->bih->biPlanes=1;
943 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
945 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
946 ogg_d->subs[ogg_d->num_sub].id = n_video;
947 n_video++;
948 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
949 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
950 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
951 // Old audio header
952 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
953 unsigned int extra_size;
954 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
955 extra_size = AV_RL16(pack.packet+140);
956 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
957 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
958 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
959 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
960 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
961 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
962 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
963 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
964 sh_a->wf->cbSize = extra_size;
965 if(extra_size > 0)
966 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
968 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
969 ogg_d->subs[ogg_d->num_sub].id = n_audio;
970 n_audio++;
971 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);
972 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
973 } else
974 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
976 // Check new header
977 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
978 pack.bytes >= (int)sizeof(stream_header)+1) {
979 stream_header *st = (stream_header*)(pack.packet+1);
980 /// New video header
981 if(strncmp(st->streamtype,"video",5) == 0) {
982 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
983 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
984 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
985 sh_v->bih->biCompression=
986 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
987 st->subtype[2],st->subtype[3]);
988 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
989 sh_v->fps = 1.0/sh_v->frametime;
990 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
991 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
992 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
993 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
994 sh_v->bih->biPlanes=1;
995 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
997 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
998 ogg_d->subs[ogg_d->num_sub].id = n_video;
999 n_video++;
1000 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1001 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
1002 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
1003 /// New audio header
1004 } else if(strncmp(st->streamtype,"audio",5) == 0) {
1005 char buffer[5];
1006 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1007 unsigned int extra_offset = 0;
1009 memcpy(buffer,st->subtype,4);
1010 buffer[4] = '\0';
1012 /* Nasty workaround. stream_header.size seems not to contain the real
1013 size in all cases. There are four extra bytes that are unaccounted
1014 for in front of the real codec initialization data _at least_ for
1015 AAC. So far I've only seen those bytes being all 0, so we can
1016 just skip them here. */
1017 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1018 extra_size -= 4;
1019 extra_offset = 4;
1022 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1023 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1024 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1025 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1026 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1027 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1028 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1029 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1030 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1031 sh_a->wf->cbSize = extra_size;
1032 if(extra_size)
1033 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1035 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1036 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1037 n_audio++;
1038 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);
1039 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1041 /// Check for text (subtitles) header
1042 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1043 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);
1044 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1045 ogg_d->subs[ogg_d->num_sub].text = 1;
1046 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1047 if (demuxer->sub->id == ogg_d->n_text)
1048 text_id = ogg_d->num_sub;
1049 new_sh_sub(demuxer, ogg_d->n_text);
1050 ogg_d->n_text++;
1051 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1052 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1053 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1054 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1055 //// Unknown header type
1056 } else
1057 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1058 /// Unknown (invalid ?) header
1059 } else
1060 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1062 if(sh_a || sh_v) {
1063 demux_stream_t* ds = NULL;
1064 if(sh_a) {
1065 // If the audio stream is not defined we took the first one
1066 if(demuxer->audio->id == -1) {
1067 demuxer->audio->id = n_audio - 1;
1068 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1070 /// Is it the stream we want
1071 if(demuxer->audio->id == n_audio - 1) {
1072 demuxer->audio->sh = sh_a;
1073 sh_a->ds = demuxer->audio;
1074 ds = demuxer->audio;
1075 audio_id = ogg_d->num_sub;
1078 if(sh_v) {
1079 /// Also for video
1080 if(demuxer->video->id == -1) {
1081 demuxer->video->id = n_video - 1;
1082 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1084 if(demuxer->video->id == n_video - 1) {
1085 demuxer->video->sh = sh_v;
1086 sh_v->ds = demuxer->video;
1087 ds = demuxer->video;
1088 video_id = ogg_d->num_sub;
1091 /// Add the header packets if the stream isn't seekable
1092 if(ds && !s->end_pos) {
1093 /// Finish the page, otherwise packets will be lost
1094 do {
1095 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1096 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1099 ogg_d->num_sub++;
1102 if(!n_video && !n_audio) {
1103 goto err_out;
1106 if(!n_video || video_id < 0)
1107 demuxer->video->id = -2;
1108 else
1109 demuxer->video->id = video_id;
1110 if(!n_audio || audio_id < 0)
1111 demuxer->audio->id = -2;
1112 else
1113 demuxer->audio->id = audio_id;
1114 /* Disable the subs only if there are no text streams at all.
1115 Otherwise the stream to display might be chosen later when the comment
1116 packet is encountered and the user used -slang instead of -sid. */
1117 if(!ogg_d->n_text)
1118 demuxer->sub->id = -2;
1119 else if (text_id >= 0) {
1120 demuxer->sub->id = text_id;
1121 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1124 ogg_d->final_granulepos=0;
1125 if(!s->end_pos)
1126 demuxer->seekable = 0;
1127 else {
1128 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1129 demuxer->movi_end = s->end_pos;
1130 demuxer->seekable = 1;
1131 demux_ogg_scan_stream(demuxer);
1134 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":"");
1136 sh_a = demuxer->audio->sh;
1137 if(sh_a)
1138 if(sh_a->format == FOURCC_VORBIS)
1139 fixup_vorbis_wf(sh_a, ogg_d);
1141 return DEMUXER_TYPE_OGG;
1143 err_out:
1144 return 0;
1148 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1149 ogg_demuxer_t* ogg_d;
1150 stream_t *s;
1151 demux_stream_t *ds;
1152 ogg_sync_state* sync;
1153 ogg_stream_state* os;
1154 ogg_page* page;
1155 ogg_packet pack;
1156 int np = 0, id=0;
1158 s = d->stream;
1159 ogg_d = d->priv;
1160 sync = &ogg_d->sync;
1161 page = &ogg_d->page;
1163 /// Find the stream we are working on
1164 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1165 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1166 return 0;
1169 while(1) {
1170 np = 0;
1171 ds = NULL;
1172 /// Try to get some packet from the current page
1173 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1174 /// No packet we go the next page
1175 if(np == 0) {
1176 while(1) {
1177 int pa,len;
1178 char *buf;
1179 ogg_d->pos += ogg_d->last_size;
1180 /// Get the next page from the physical stream
1181 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1182 /// Error : we skip some bytes
1183 if(pa < 0) {
1184 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1185 ogg_d->pos -= pa;
1186 continue;
1188 /// We need more data
1189 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1190 len = stream_read(s,buf,BLOCK_SIZE);
1191 if(len == 0 && s->eof) {
1192 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1193 return 0;
1195 ogg_sync_wrote(sync,len);
1196 } /// Page loop
1197 ogg_d->last_size = pa;
1198 /// Find the page's logical stream
1199 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1200 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1201 return 0;
1203 /// Take the page
1204 if(ogg_stream_pagein(os,page) == 0)
1205 break;
1206 /// Page was invalid => retry
1207 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1208 ogg_d->pos += ogg_d->last_size;
1210 } else /// Packet was corrupted
1211 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1212 } /// Packet loop
1214 /// Is the actual logical stream in use ?
1215 if(id == d->audio->id)
1216 ds = d->audio;
1217 else if(id == d->video->id)
1218 ds = d->video;
1219 else if (ogg_d->subs[id].text)
1220 ds = d->sub;
1222 if(ds) {
1223 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1224 continue; /// Unuseful packet, get another
1225 d->filepos = ogg_d->pos;
1226 return 1;
1229 } /// while(1)
1233 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1234 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1235 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1236 demuxer_t *od;
1237 ogg_demuxer_t *ogg_d;
1238 stream_t* s;
1239 uint32_t hdrsizes[3];
1240 demux_packet_t *dp;
1241 sh_audio_t *sh_audio = demuxer->audio->sh;
1242 int np;
1243 uint8_t *extradata = sh_audio->wf + 1;
1244 int i;
1245 unsigned char *p = NULL,*buf;
1246 int plen;
1248 /// Check that the cbSize is big enough for the following reads
1249 if(sh_audio->wf->cbSize < 22+3*4) {
1250 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1251 goto fallback;
1253 /// Get the size of the 3 header packet
1254 extradata += 22;
1255 for (i = 0; i < 3; i++) {
1256 hdrsizes[i] = AV_RL32(extradata);
1257 extradata += 4;
1259 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1261 /// Check the size
1262 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1263 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1264 goto fallback;
1267 // Build the ogg demuxer private datas
1268 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1269 ogg_d->num_sub = 1;
1270 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1271 ogg_d->subs[0].vorbis = 1;
1273 // Init the ogg physical stream
1274 ogg_sync_init(&ogg_d->sync);
1276 // Get the first page of the stream : we assume there only 1 logical stream
1277 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1278 if(np < 0) {
1279 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1280 free(ogg_d);
1281 goto fallback;
1283 // Add some data
1284 plen = ds_get_packet(demuxer->audio,&p);
1285 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1286 memcpy(buf,p,plen);
1287 ogg_sync_wrote(&ogg_d->sync,plen);
1289 // Init the logical stream
1290 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1291 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1292 // Write the page
1293 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1295 // Create the ds_stream and the ogg demuxer
1296 s = new_ds_stream(demuxer->audio);
1297 od = new_demuxer(s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1299 /// Add the header packets in the ogg demuxer audio stream
1300 for (i = 0; i < 3; i++) {
1301 dp = new_demux_packet(hdrsizes[i]);
1302 memcpy(dp->buffer,extradata,hdrsizes[i]);
1303 ds_add_packet(od->audio,dp);
1304 extradata += hdrsizes[i];
1307 // Finish setting up the ogg demuxer
1308 od->priv = ogg_d;
1309 sh_audio = new_sh_audio(od,0);
1310 od->audio->id = 0;
1311 od->video->id = -2;
1312 od->audio->sh = sh_audio;
1313 sh_audio->ds = od->audio;
1314 sh_audio->format = FOURCC_VORBIS;
1315 fixup_vorbis_wf(sh_audio, ogg_d);
1317 /// Return the joined demuxers
1318 return new_demuxers_demuxer(demuxer,od,demuxer);
1320 fallback:
1321 demuxer->audio->id = -2;
1322 return demuxer;
1326 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1327 ogg_demuxer_t* ogg_d = demuxer->priv;
1328 ogg_sync_state* sync = &ogg_d->sync;
1329 ogg_page* page= &ogg_d->page;
1330 ogg_stream_state* oss;
1331 ogg_stream_t* os;
1332 demux_stream_t* ds;
1333 ogg_packet op;
1334 float rate;
1335 int i,sp,first,precision=1,do_seek=1;
1336 vorbis_info* vi = NULL;
1337 int64_t gp = 0, old_gp;
1338 off_t pos, old_pos;
1339 int np;
1340 int is_gp_valid;
1341 float pts;
1342 int is_keyframe;
1343 int samplesize=1;
1344 ogg_int64_t granulepos_orig;
1346 if(demuxer->video->id >= 0) {
1347 ds = demuxer->video;
1348 rate = ogg_d->subs[ds->id].samplerate;
1349 } else {
1350 ds = demuxer->audio;
1351 os = &ogg_d->subs[ds->id];
1352 vi = &(os->vi);
1353 rate = (float)vi->rate;
1354 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1357 os = &ogg_d->subs[ds->id];
1358 oss = &os->stream;
1360 old_gp = os->lastpos;
1361 old_pos = ogg_d->pos;
1363 //calculate the granulepos to seek to
1364 gp = flags & SEEK_ABSOLUTE ? 0 : os->lastpos;
1365 if(flags & SEEK_FACTOR) {
1366 if (ogg_d->final_granulepos > 0)
1367 gp += ogg_d->final_granulepos * rel_seek_secs;
1368 else
1369 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1370 } else
1371 gp += rel_seek_secs * rate;
1372 if (gp < 0) gp = 0;
1374 //calculate the filepos to seek to
1375 if(ogg_d->syncpoints) {
1376 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1377 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1380 if(sp >= ogg_d->num_syncpoint) return;
1381 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1382 sp--;
1383 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1384 if (sp > 0 && gp < os->lastpos) sp--;
1385 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1387 pos = ogg_d->syncpoints[sp].page_pos;
1388 precision = 0;
1389 } else {
1390 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1391 if(flags & SEEK_FACTOR)
1392 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1393 else {
1394 if (ogg_d->final_granulepos > 0) {
1395 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);
1396 } else if (os->lastpos > 0) {
1397 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1400 if (pos < 0) pos = 0;
1401 if (pos > (demuxer->movi_end - demuxer->movi_start))
1402 pos = demuxer->movi_end - demuxer->movi_start;
1403 } // if(ogg_d->syncpoints)
1405 while(1) {
1406 if (do_seek) {
1407 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1408 ogg_sync_reset(sync);
1409 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1410 ogg_stream_reset(&ogg_d->subs[i].stream);
1411 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1413 ogg_d->pos = pos;
1414 ogg_d->last_size = 0;
1415 /* we just guess that we reached correct granulepos, in case a
1416 subsequent search occurs before we read a valid granulepos */
1417 os->lastpos = gp;
1418 first = !(ogg_d->syncpoints);
1419 do_seek=0;
1421 ogg_d->pos += ogg_d->last_size;
1422 ogg_d->last_size = 0;
1423 np = ogg_sync_pageseek(sync,page);
1425 if(np < 0)
1426 ogg_d->pos -= np;
1427 if(np <= 0) { // We need more data
1428 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1429 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1430 if(len == 0 && demuxer->stream->eof) {
1431 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1432 return;
1434 ogg_sync_wrote(sync,len);
1435 continue;
1437 ogg_d->last_size = np;
1438 if(ogg_page_serialno(page) != oss->serialno)
1439 continue;
1441 if(ogg_stream_pagein(oss,page) != 0)
1442 continue;
1444 while(1) {
1445 np = ogg_stream_packetout(oss,&op);
1446 if(np < 0)
1447 continue;
1448 else if(np == 0)
1449 break;
1450 if (first) { /* Discard the first packet as it's probably broken,
1451 and we don't have any other means to decide whether it is
1452 complete or not. */
1453 first = 0;
1454 break;
1456 is_gp_valid = (op.granulepos >= 0);
1457 granulepos_orig=op.granulepos;
1458 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1459 if (precision && is_gp_valid) {
1460 precision--;
1461 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1462 //prepare another seek because we are off by more than 1s
1463 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1464 if (pos < 0) pos = 0;
1465 if (pos < demuxer->movi_end - demuxer->movi_start) {
1466 do_seek=1;
1467 break;
1471 if (is_gp_valid && pos > 0 && old_gp > gp
1472 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1473 /* prepare another seek because looking for a syncpoint
1474 destroyed the backward search */
1475 pos = old_pos - 1.5 * (old_pos - pos);
1476 if (pos < 0) pos = 0;
1477 if (pos < demuxer->movi_end - demuxer->movi_start) {
1478 do_seek=1;
1479 break;
1482 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1483 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1484 vo_sub = &ogg_sub;
1485 vo_osd_changed(OSDTYPE_SUBTITLE);
1487 op.granulepos=granulepos_orig;
1488 demux_ogg_add_packet(ds,os,ds->id,&op);
1489 return;
1494 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1498 static void demux_close_ogg(demuxer_t* demuxer) {
1499 ogg_demuxer_t* ogg_d = demuxer->priv;
1500 ogg_stream_t* os = NULL;
1501 int i;
1503 if(!ogg_d)
1504 return;
1506 #ifdef CONFIG_ICONV
1507 subcp_close();
1508 #endif
1510 ogg_sync_clear(&ogg_d->sync);
1511 if(ogg_d->subs)
1513 for (i = 0; i < ogg_d->num_sub; i++)
1515 os = &ogg_d->subs[i];
1516 ogg_stream_clear(&os->stream);
1517 if(os->vi_initialized)
1518 vorbis_info_clear(&os->vi);
1520 free(ogg_d->subs);
1522 if(ogg_d->syncpoints)
1523 free(ogg_d->syncpoints);
1524 if (ogg_d->text_ids)
1525 free(ogg_d->text_ids);
1526 if (ogg_d->text_langs) {
1527 for (i = 0; i < ogg_d->n_text; i++)
1528 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1529 free(ogg_d->text_langs);
1531 free(ogg_d);
1534 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1535 ogg_demuxer_t* ogg_d = demuxer->priv;
1536 ogg_stream_t* os;
1537 float rate;
1539 if(demuxer->video->id >= 0) {
1540 os = &ogg_d->subs[demuxer->video->id];
1541 rate = os->samplerate;
1542 } else {
1543 os = &ogg_d->subs[demuxer->audio->id];
1544 rate = os->vi.rate;
1548 switch(cmd) {
1549 case DEMUXER_CTRL_GET_TIME_LENGTH:
1550 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1551 *(double *)arg=(double)ogg_d->final_granulepos / rate;
1552 return DEMUXER_CTRL_GUESS;
1554 case DEMUXER_CTRL_GET_PERCENT_POS:
1555 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1556 *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos;
1557 return DEMUXER_CTRL_OK;
1559 default:
1560 return DEMUXER_CTRL_NOTIMPL;
1566 const demuxer_desc_t demuxer_desc_ogg = {
1567 "Ogg demuxer",
1568 "ogg",
1569 "Ogg",
1570 "?",
1572 DEMUXER_TYPE_OGG,
1573 1, // safe autodetect
1574 demux_ogg_open,
1575 demux_ogg_fill_buffer,
1576 NULL,
1577 demux_close_ogg,
1578 demux_ogg_seek,
1579 demux_ogg_control