Ignore svn changes up to r30559
[mplayer/kovensky.git] / libmpdemux / demux_ogg.c
blob2bd6781cf246b13880c93f23b03aa5754cf4bff1
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "config.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <math.h>
26 #include <inttypes.h>
28 #include "options.h"
29 #include "mp_msg.h"
30 #include "help_mp.h"
31 #include "stream/stream.h"
32 #include "demuxer.h"
33 #include "stheader.h"
34 #include "ffmpeg_files/intreadwrite.h"
36 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
37 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
38 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
40 #ifdef CONFIG_TREMOR
41 #include <tremor/ogg.h>
42 #include <tremor/ivorbiscodec.h>
43 #else
44 #include <ogg/ogg.h>
45 #include <vorbis/codec.h>
46 #endif
48 #ifdef CONFIG_OGGTHEORA
49 #include <theora/theora.h>
50 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
51 #endif
53 #define BLOCK_SIZE 4096
55 /* Theora decoder context : we won't be able to interpret granule positions
56 * without using theora_granule_time with the theora_state of the stream.
57 * This is duplicated in `vd_theora.c'; put this in a common header?
59 #ifdef CONFIG_OGGTHEORA
60 typedef struct theora_struct_st {
61 theora_state st;
62 theora_comment cc;
63 theora_info inf;
64 } theora_struct_t;
65 #endif
67 //// OggDS headers
68 // Header for the new header format
69 typedef struct stream_header_video
71 ogg_int32_t width;
72 ogg_int32_t height;
73 } stream_header_video;
75 typedef struct stream_header_audio
77 ogg_int16_t channels;
78 ogg_int16_t blockalign;
79 ogg_int32_t avgbytespersec;
80 } stream_header_audio;
82 typedef struct __attribute__((__packed__)) stream_header
84 char streamtype[8];
85 char subtype[4];
87 ogg_int32_t size; // size of the structure
89 ogg_int64_t time_unit; // in reference time
90 ogg_int64_t samples_per_unit;
91 ogg_int32_t default_len; // in media time
93 ogg_int32_t buffersize;
94 ogg_int16_t bits_per_sample;
96 ogg_int16_t padding;
98 union
100 // Video specific
101 stream_header_video video;
102 // Audio specific
103 stream_header_audio audio;
104 } sh;
105 } stream_header;
107 /// Our private datas
109 typedef struct ogg_syncpoint {
110 int64_t granulepos;
111 off_t page_pos;
112 } ogg_syncpoint_t;
114 /// A logical stream
115 typedef struct ogg_stream {
116 /// Timestamping stuff
117 float samplerate; /// granulpos 2 time
118 int64_t lastpos;
119 int32_t lastsize;
120 int keyframe_frequency_force;
122 // Logical stream state
123 ogg_stream_state stream;
124 int hdr_packets;
125 int vorbis;
126 int speex;
127 int theora;
128 int flac;
129 int text;
130 int id;
132 vorbis_info vi;
133 int vi_initialized;
135 void *ogg_d;
136 } ogg_stream_t;
138 typedef struct ogg_demuxer {
139 /// Physical stream state
140 ogg_sync_state sync;
141 /// Current page
142 ogg_page page;
143 /// Logical streams
144 ogg_stream_t *subs;
145 int num_sub;
146 ogg_syncpoint_t* syncpoints;
147 int num_syncpoint;
148 off_t pos, last_size;
149 int64_t initial_granulepos;
150 int64_t final_granulepos;
151 int64_t duration;
153 /* Used for subtitle switching. */
154 int n_text;
155 int *text_ids;
156 char **text_langs;
157 } ogg_demuxer_t;
159 #define NUM_VORBIS_HDR_PACKETS 3
161 /// Some defines from OggDS
162 #define PACKET_TYPE_HEADER 0x01
163 #define PACKET_TYPE_BITS 0x07
164 #define PACKET_LEN_BITS01 0xc0
165 #define PACKET_LEN_BITS2 0x02
166 #define PACKET_IS_SYNCPOINT 0x08
168 extern char *dvdsub_lang, *audio_lang;
170 //-------- subtitle support - should be moved to decoder layer, and queue
171 // - subtitles up in demuxer buffer...
173 #include "subreader.h"
174 #include "libvo/sub.h"
175 #define OGG_SUB_MAX_LINE 128
177 static subtitle ogg_sub;
178 //FILE* subout;
180 static void demux_ogg_add_sub (ogg_stream_t* os,ogg_packet* pack) {
181 int lcv;
182 char *packet = pack->packet;
184 if (pack->bytes < 4)
185 return;
186 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
187 (unsigned char)packet[0],
188 (unsigned char)packet[1],
189 (unsigned char)packet[2],
190 &packet[3]);
192 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
193 // Find data start
194 double endpts = MP_NOPTS_VALUE;
195 int32_t duration = 0;
196 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
197 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
198 lcv = 1 + hdrlen;
199 if (pack->bytes < lcv)
200 return;
201 for (i = hdrlen; i > 0; i--) {
202 duration <<= 8;
203 duration |= (unsigned char)packet[i];
205 if (hdrlen > 0 && duration > 0) {
206 float pts;
207 if(pack->granulepos == -1)
208 pack->granulepos = os->lastpos + os->lastsize;
209 pts = (float)pack->granulepos/(float)os->samplerate;
210 endpts = 1.0 + pts + (float)duration/1000.0;
212 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
213 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
216 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
217 ogg_sub.lines, ogg_sub.text[0]);
218 #ifdef CONFIG_ICONV
219 subcp_recode(&ogg_sub);
220 #endif
221 vo_sub = &ogg_sub;
222 vo_osd_changed(OSDTYPE_SUBTITLE);
226 // get the logical stream of the current page
227 // fill os if non NULL and return the stream id
228 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
229 int id,s_no;
230 ogg_page* page = &ogg_d->page;
232 s_no = ogg_page_serialno(page);
234 for(id= 0; id < ogg_d->num_sub ; id++) {
235 if(s_no == ogg_d->subs[id].stream.serialno)
236 break;
239 if(id == ogg_d->num_sub) {
240 // If we have only one vorbis stream allow the stream id to change
241 // it's normal on radio stream (each song have an different id).
242 // But we (or the codec?) should check that the samplerate, etc
243 // doesn't change (for radio stream it's ok)
244 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
245 ogg_stream_reset(&ogg_d->subs[0].stream);
246 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
247 id = 0;
248 } else
249 return -1;
252 if(os)
253 *os = &ogg_d->subs[id].stream;
255 return id;
259 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
260 unsigned char* data = pack->packet;
262 *pts = 0;
263 *flags = 0;
265 if(os->vorbis) {
266 if(*pack->packet & PACKET_TYPE_HEADER)
267 os->hdr_packets++;
268 else
270 vorbis_info *vi;
271 int32_t blocksize = 0;
273 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
274 vi = os->vi_initialized ? &os->vi : NULL;
275 if (vi)
276 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
277 // Calculate the timestamp if the packet don't have any
278 if(pack->granulepos == -1) {
279 pack->granulepos = os->lastpos;
280 if(os->lastsize > 0)
281 pack->granulepos += os->lastsize;
282 } else
283 *flags = 1;
284 if (vi)
285 *pts = pack->granulepos / (float)vi->rate;
286 os->lastsize = blocksize;
287 os->lastpos = pack->granulepos;
289 } else if (os->speex) {
290 // whole packet (default)
291 # ifdef CONFIG_OGGTHEORA
292 } else if (os->theora) {
293 /* we pass complete packets to theora, mustn't strip the header! */
294 os->lastsize = 1;
296 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
297 have theora_state st, until all header packets were passed to the
298 decoder. */
299 if (!(*data&0x80))
301 int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
302 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
304 if (pack->granulepos >= 0)
306 os->lastpos = pack->granulepos >> keyframe_granule_shift;
307 os->lastpos += pack->granulepos & iframemask;
308 *flags = (pack->granulepos & iframemask) == 0;
310 else
312 os->lastpos++;
314 pack->granulepos = os->lastpos;
315 *pts = (double)os->lastpos / (double)os->samplerate;
317 #endif /* CONFIG_OGGTHEORA */
318 } else if (os->flac) {
319 /* we pass complete packets to flac, mustn't strip the header! */
320 if (os->flac == 2 && pack->packet[0] != 0xff)
321 return NULL;
322 } else {
323 if(*pack->packet & PACKET_TYPE_HEADER)
324 os->hdr_packets++;
325 else {
326 // Find data start
327 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
328 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
329 data = pack->packet + 1 + hdrlen;
330 // Calculate the timestamp
331 if(pack->granulepos == -1)
332 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
333 // If we already have a timestamp it can be a syncpoint
334 if(*pack->packet & PACKET_IS_SYNCPOINT)
335 *flags = 1;
336 *pts = pack->granulepos/os->samplerate;
337 // Save the packet length and timestamp
338 os->lastsize = 0;
339 while(hdrlen) {
340 os->lastsize <<= 8;
341 os->lastsize |= pack->packet[hdrlen];
342 hdrlen--;
344 os->lastpos = pack->granulepos;
347 return data;
350 // check if clang has substring from comma separated langlist
351 static int demux_ogg_check_lang(const char *clang, const char *langlist)
353 const char *c;
355 if (!langlist || !*langlist)
356 return 0;
357 while ((c = strchr(langlist, ',')))
359 if (!strncasecmp(clang, langlist, c - langlist))
360 return 1;
361 langlist = &c[1];
363 if (!strncasecmp(clang, langlist, strlen(langlist)))
364 return 1;
365 return 0;
368 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id);
370 /// Try to print out comments and also check for LANGUAGE= tag
371 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
373 const char *hdr, *val;
374 char **cmt = vc->user_comments;
375 int index, i;
376 ogg_demuxer_t *ogg_d = d->priv;
377 static const struct table {
378 const char *ogg;
379 const char *mp;
380 } table[] = {
381 { "ENCODED_USING", "Software" },
382 { "ENCODER_URL", "Encoder URL" },
383 { "TITLE", "Title" },
384 { "ARTIST", "Artist" },
385 { "COMMENT", "Comments" },
386 { "DATE", "Creation Date" },
387 { "GENRE", "Genre" },
388 { "ALBUM", "Album" },
389 { "TRACKNUMBER", "Track" },
390 { NULL, NULL },
393 while(*cmt)
395 hdr = NULL;
396 if (!strncasecmp(*cmt, "LANGUAGE=", 9))
398 val = *cmt + 9;
399 if (ogg_d->subs[id].text)
400 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
401 else if (id != d->video->id)
402 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
403 if (ogg_d->subs[id].text)
404 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
405 // copy this language name into the array
406 index = demux_ogg_sub_reverse_id(d, id);
407 if (index >= 0) {
408 sh_sub_t* sh;
409 // in case of malicious files with more than one lang per track:
410 if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
411 ogg_d->text_langs[index] = strdup(val);
412 sh = d->s_streams[index];
413 if (sh && sh->lang) free(sh->lang);
414 if (sh) sh->lang = strdup(val);
416 // check for -slang if subs are uninitialized yet
417 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
419 d->sub->id = index;
420 d->opts->sub_id = index;
421 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
423 else
424 hdr = "Language";
426 else {
427 for (i = 0; table[i].ogg; i++)
429 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
430 (*cmt)[strlen(table[i].ogg)] == '=')
432 hdr = table[i].mp;
433 val = *cmt + strlen(table[i].ogg) + 1;
437 if (hdr)
438 demux_info_add(d, hdr, val);
439 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
440 cmt++;
444 /// Calculate the timestamp and add the packet to the demux stream
445 // return 1 if the packet was added, 0 otherwise
446 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
447 demuxer_t* d = ds->demuxer;
448 demux_packet_t* dp;
449 unsigned char* data;
450 float pts = 0;
451 int flags = 0;
452 int samplesize = 1;
454 // If packet is an comment header then we try to get comments at first
455 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
457 vorbis_info vi;
458 vorbis_comment vc;
460 vorbis_info_init(&vi);
461 vorbis_comment_init(&vc);
462 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
463 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
464 demux_ogg_check_comments(d, os, id, &vc);
465 vorbis_comment_clear(&vc);
466 vorbis_info_clear(&vi);
468 if (os->text) {
469 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
470 demux_ogg_add_sub(os,pack);
471 return 0;
473 if (os->speex) {
474 // discard first two packets, they contain the header and comment
475 if (os->hdr_packets < 2) {
476 os->hdr_packets++;
477 return 0;
479 } else
480 // If packet is an header we jump it except for vorbis and theora
481 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
482 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
483 // handled differently for each and every stream type. The joy! The joy!
484 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
485 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
486 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
487 return 0;
489 // For vorbis packet the packet is the data, for other codec we must jump
490 // the header
491 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
492 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
494 data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
495 if (!data)
496 return 0;
498 /// Clear subtitles if necessary (for broken files)
499 if (sub_clear_text(&ogg_sub, pts)) {
500 vo_sub = &ogg_sub;
501 vo_osd_changed(OSDTYPE_SUBTITLE);
503 /// Send the packet
504 dp = new_demux_packet(pack->bytes-(data-pack->packet));
505 memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
506 dp->pts = pts;
507 dp->flags = flags;
508 ds_add_packet(ds,dp);
509 mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
510 dp, ds, pts, dp->len, flags);
511 return 1;
514 /// if -forceidx build a table of all syncpoints to make seeking easier
515 /// otherwise try to get at least the final_granulepos
516 static void demux_ogg_scan_stream(demuxer_t* demuxer) {
517 ogg_demuxer_t* ogg_d = demuxer->priv;
518 stream_t *s = demuxer->stream;
519 ogg_sync_state* sync = &ogg_d->sync;
520 ogg_page* page= &ogg_d->page;
521 ogg_stream_state* oss;
522 ogg_stream_t* os;
523 ogg_packet op;
524 int np,sid,p,samplesize=1;
525 off_t pos, last_pos;
526 pos = last_pos = demuxer->movi_start;
528 // Reset the stream
529 stream_seek(s,demuxer->movi_start);
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) {
578 ogg_d->final_granulepos = op.granulepos;
579 if(ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
580 ogg_d->initial_granulepos = op.granulepos;
581 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end-2*270000) {
582 //the 270000 are just a wild guess
583 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
584 ogg_sync_reset(sync);
585 continue;
589 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
590 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
591 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
592 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
593 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
594 ogg_d->num_syncpoint++;
596 p++;
598 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
599 last_pos = pos;
600 pos += np;
601 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
603 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
605 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
606 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
608 stream_reset(s);
609 stream_seek(s,demuxer->movi_start);
610 ogg_sync_reset(sync);
611 for(np = 0 ; np < ogg_d->num_sub ; np++) {
612 ogg_stream_reset(&ogg_d->subs[np].stream);
613 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
617 // Get the first page
618 while(1) {
619 np = ogg_sync_pageout(sync,page);
620 if(np <= 0) { // We need more data
621 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
622 int len = stream_read(s,buf,BLOCK_SIZE);
623 if(len == 0 && s->eof) {
624 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
625 break;
628 ogg_sync_wrote(sync,len);
629 continue;
631 demux_ogg_get_page_stream(ogg_d,&oss);
632 ogg_stream_pagein(oss,page);
633 break;
638 void print_wave_header(WAVEFORMATEX *h, int verbose_level);
639 void print_video_header(BITMAPINFOHEADER *h, int verbose_level);
641 /* defined in demux_mov.c */
642 unsigned int store_ughvlc(unsigned char *s, unsigned int v);
644 /** \brief Change the current subtitle stream and return its ID.
646 \param demuxer The demuxer whose subtitle stream will be changed.
647 \param new_num The number of the new subtitle track. The number must be
648 between 0 and ogg_d->n_text - 1.
650 \returns The Ogg stream number ( = page serial number) of the newly selected
651 track.
653 int demux_ogg_sub_id(demuxer_t *demuxer, int index) {
654 ogg_demuxer_t *ogg_d = demuxer->priv;
655 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
658 /** \brief Translate the ogg track number into the subtitle number.
659 * \param demuxer The demuxer about whose subtitles we are inquiring.
660 * \param id The ogg track number of the subtitle track.
662 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
663 ogg_demuxer_t *ogg_d = demuxer->priv;
664 int i;
665 for (i = 0; i < ogg_d->n_text; i++)
666 if (ogg_d->text_ids[i] == id) return i;
667 return -1;
670 static void demux_close_ogg(demuxer_t* demuxer);
672 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
674 int i, offset;
675 int ris, init_error = 0;
676 ogg_packet op[3];
677 unsigned char *buf[3];
678 unsigned char *ptr;
679 unsigned int len;
680 ogg_stream_t *os = &od->subs[sh->ds->id];
681 vorbis_comment vc;
683 vorbis_info_init(&os->vi);
684 vorbis_comment_init(&vc);
685 for(i = 0; i < 3; i++) {
686 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
687 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
688 if(op[i].bytes < 0) {
689 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
690 return;
692 buf[i] = malloc(op[i].bytes);
693 if(!buf[i])
694 return;
695 memcpy(buf[i], op[i].packet, op[i].bytes);
697 op[i].b_o_s = (i==0);
698 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
699 if(ris < 0) {
700 init_error = 1;
701 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
704 vorbis_comment_clear(&vc);
705 if(!init_error)
706 os->vi_initialized = 1;
708 len = op[0].bytes + op[1].bytes + op[2].bytes;
709 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
710 ptr = (unsigned char*) (sh->wf+1);
712 ptr[0] = 2;
713 offset = 1;
714 offset += store_ughvlc(&ptr[offset], op[0].bytes);
715 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
716 offset += store_ughvlc(&ptr[offset], op[1].bytes);
717 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
718 for(i = 0; i < 3; i++) {
719 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
720 memcpy(&ptr[offset], buf[i], op[i].bytes);
721 offset += op[i].bytes;
723 sh->wf->cbSize = offset;
724 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
725 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
727 if(op[0].bytes >= 29) {
728 unsigned int br;
729 int nombr, minbr, maxbr;
730 ptr = buf[0];
731 sh->channels = ptr[11];
732 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
733 maxbr = AV_RL32(&ptr[16]); //max
734 nombr = AV_RL32(&ptr[20]); //nominal
735 minbr = AV_RL32(&ptr[24]); //minimum
737 if(maxbr == -1)
738 maxbr = 0;
739 if(nombr == -1)
740 nombr = 0;
741 if(minbr == -1)
742 minbr = 0;
744 br = maxbr / 8;
745 if(!br)
746 br = nombr / 8;
747 if(!br)
748 br = minbr / 8;
749 sh->wf->nAvgBytesPerSec = br;
750 sh->wf->wBitsPerSample = 16;
751 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
753 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",
754 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
756 free(buf[2]);
757 free(buf[1]);
758 free(buf[0]);
762 /// Open an ogg physical stream
763 // Not static because it's used also in demuxer_avi.c
764 int demux_ogg_open(demuxer_t* demuxer) {
765 ogg_demuxer_t* ogg_d;
766 stream_t *s;
767 char* buf;
768 int np,s_no, n_audio = 0, n_video = 0;
769 int audio_id = -1, video_id = -1, text_id = -1;
770 ogg_sync_state* sync;
771 ogg_page* page;
772 ogg_packet pack;
773 sh_audio_t* sh_a;
774 sh_video_t* sh_v;
776 #ifdef CONFIG_ICONV
777 subcp_open(NULL);
778 #endif
780 s = demuxer->stream;
782 demuxer->priv =
783 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
784 sync = &ogg_d->sync;
785 page = &ogg_d->page;
787 ogg_sync_init(sync);
789 while(1) {
790 /// Try to get a page
791 ogg_d->pos += ogg_d->last_size;
792 np = ogg_sync_pageseek(sync,page);
793 /// Error
794 if(np < 0) {
795 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
796 goto err_out;
798 /// Need some more data
799 if(np == 0) {
800 int len;
801 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
802 len = stream_read(s,buf,BLOCK_SIZE);
803 if(len == 0 && s->eof) {
804 goto err_out;
806 ogg_sync_wrote(sync,len);
807 continue;
809 ogg_d->last_size = np;
810 // We got one page now
812 if( ! ogg_page_bos(page) ) { // It's not a beginning page
813 // Header parsing end here, we need to get the page otherwise it will be lost
814 int id = demux_ogg_get_page_stream(ogg_d,NULL);
815 if(id >= 0)
816 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
817 else
818 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
819 break;
822 /// Init the data structure needed for a logical stream
823 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
824 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
825 /// Get the stream serial number
826 s_no = ogg_page_serialno(page);
827 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
828 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
829 // Take the first page
830 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
831 // Get first packet of the page
832 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
834 // Reset our vars
835 sh_a = NULL;
836 sh_v = NULL;
838 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
840 // Check for Vorbis
841 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
842 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
843 sh_a->format = FOURCC_VORBIS;
844 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
845 ogg_d->subs[ogg_d->num_sub].id = n_audio;
846 n_audio++;
847 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
848 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
849 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
850 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
851 sh_a->format = FOURCC_SPEEX;
852 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
853 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
854 sh_a->wf->wFormatTag = sh_a->format;
855 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
856 sh_a->wf->nBlockAlign = 0;
857 sh_a->wf->wBitsPerSample = 16;
858 sh_a->samplesize = 2;
859 sh_a->wf->cbSize = pack.bytes;
860 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
862 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
863 ogg_d->subs[ogg_d->num_sub].speex = 1;
864 ogg_d->subs[ogg_d->num_sub].id = n_audio;
865 n_audio++;
866 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
868 // check for Theora
869 # ifdef CONFIG_OGGTHEORA
870 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
871 int errorCode = 0;
872 theora_info inf;
873 theora_comment cc;
875 theora_info_init (&inf);
876 theora_comment_init (&cc);
878 errorCode = theora_decode_header (&inf, &cc, &pack);
879 if (errorCode)
880 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
881 errorCode);
882 else
884 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
886 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
887 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
888 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
889 sh_v->fps = ((double)inf.fps_numerator)/
890 (double)inf.fps_denominator;
891 sh_v->frametime = ((double)inf.fps_denominator)/
892 (double)inf.fps_numerator;
893 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
894 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
895 sh_v->bih->biBitCount = 24;
896 sh_v->bih->biPlanes = 3;
897 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
898 sh_v->bih->biWidth*sh_v->bih->biHeight);
899 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
900 ogg_d->subs[ogg_d->num_sub].theora = 1;
901 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
902 ogg_d->subs[ogg_d->num_sub].id = n_video;
903 n_video++;
904 mp_msg(MSGT_DEMUX,MSGL_INFO,
905 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
906 ogg_d->num_sub,
907 (int)inf.version_major,
908 (int)inf.version_minor,
909 (int)inf.version_subminor,
910 n_video - 1);
911 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
913 theora_comment_clear(&cc);
914 theora_info_clear(&inf);
915 # endif /* CONFIG_OGGTHEORA */
916 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
917 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
918 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
919 ogg_d->subs[ogg_d->num_sub].id = n_audio;
920 n_audio++;
921 ogg_d->subs[ogg_d->num_sub].flac = 1;
922 sh_a->wf = NULL;
923 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
924 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
925 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
926 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
927 ogg_d->subs[ogg_d->num_sub].id = n_audio;
928 n_audio++;
929 ogg_d->subs[ogg_d->num_sub].flac = 2;
930 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
931 sh_a->wf->wFormatTag = sh_a->format;
932 sh_a->wf->cbSize = 34;
933 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
934 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
936 /// Check for old header
937 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
939 // Old video header
940 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
941 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
942 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
943 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
944 sh_v->bih->biCompression=
945 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
946 pack.packet[70],pack.packet[71]);
947 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
948 sh_v->fps = 1/sh_v->frametime;
949 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
950 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
951 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
952 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
953 sh_v->bih->biPlanes=1;
954 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
956 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
957 ogg_d->subs[ogg_d->num_sub].id = n_video;
958 n_video++;
959 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
960 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
961 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
962 // Old audio header
963 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
964 unsigned int extra_size;
965 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
966 extra_size = AV_RL16(pack.packet+140);
967 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
968 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
969 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
970 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
971 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
972 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
973 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
974 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
975 sh_a->wf->cbSize = extra_size;
976 if(extra_size > 0)
977 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
979 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
980 ogg_d->subs[ogg_d->num_sub].id = n_audio;
981 n_audio++;
982 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);
983 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
984 } else
985 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
987 // Check new header
988 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
989 pack.bytes >= (int)sizeof(stream_header)+1) {
990 stream_header *st = (stream_header*)(pack.packet+1);
991 /// New video header
992 if(strncmp(st->streamtype,"video",5) == 0) {
993 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
994 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
995 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
996 sh_v->bih->biCompression=
997 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
998 st->subtype[2],st->subtype[3]);
999 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
1000 sh_v->fps = 1.0/sh_v->frametime;
1001 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
1002 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
1003 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1004 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
1005 sh_v->bih->biPlanes=1;
1006 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
1008 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
1009 ogg_d->subs[ogg_d->num_sub].id = n_video;
1010 n_video++;
1011 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1012 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
1013 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
1014 /// New audio header
1015 } else if(strncmp(st->streamtype,"audio",5) == 0) {
1016 char buffer[5];
1017 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1018 unsigned int extra_offset = 0;
1020 memcpy(buffer,st->subtype,4);
1021 buffer[4] = '\0';
1023 /* Nasty workaround. stream_header.size seems not to contain the real
1024 size in all cases. There are four extra bytes that are unaccounted
1025 for in front of the real codec initialization data _at least_ for
1026 AAC. So far I've only seen those bytes being all 0, so we can
1027 just skip them here. */
1028 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1029 extra_size -= 4;
1030 extra_offset = 4;
1033 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1034 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1035 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1036 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1037 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1038 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1039 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1040 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1041 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1042 sh_a->wf->cbSize = extra_size;
1043 if(extra_size)
1044 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1046 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1047 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1048 n_audio++;
1049 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);
1050 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1052 /// Check for text (subtitles) header
1053 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1054 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);
1055 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1056 ogg_d->subs[ogg_d->num_sub].text = 1;
1057 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1058 if (demuxer->sub->id == ogg_d->n_text)
1059 text_id = ogg_d->num_sub;
1060 new_sh_sub(demuxer, ogg_d->n_text);
1061 ogg_d->n_text++;
1062 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1063 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1064 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1065 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1066 //// Unknown header type
1067 } else
1068 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1069 /// Unknown (invalid ?) header
1070 } else
1071 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1073 if(sh_a || sh_v) {
1074 demux_stream_t* ds = NULL;
1075 if(sh_a) {
1076 // If the audio stream is not defined we took the first one
1077 if(demuxer->audio->id == -1) {
1078 demuxer->audio->id = n_audio - 1;
1079 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1081 /// Is it the stream we want
1082 if(demuxer->audio->id == n_audio - 1) {
1083 demuxer->audio->sh = sh_a;
1084 sh_a->ds = demuxer->audio;
1085 ds = demuxer->audio;
1086 audio_id = ogg_d->num_sub;
1089 if(sh_v) {
1090 /// Also for video
1091 if(demuxer->video->id == -1) {
1092 demuxer->video->id = n_video - 1;
1093 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1095 if(demuxer->video->id == n_video - 1) {
1096 demuxer->video->sh = sh_v;
1097 sh_v->ds = demuxer->video;
1098 ds = demuxer->video;
1099 video_id = ogg_d->num_sub;
1102 /// Add the header packets if the stream isn't seekable
1103 if(ds && !s->end_pos) {
1104 /// Finish the page, otherwise packets will be lost
1105 do {
1106 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1107 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1110 ogg_d->num_sub++;
1113 if(!n_video && !n_audio) {
1114 goto err_out;
1117 if(!n_video || video_id < 0)
1118 demuxer->video->id = -2;
1119 else
1120 demuxer->video->id = video_id;
1121 if(!n_audio || audio_id < 0)
1122 demuxer->audio->id = -2;
1123 else
1124 demuxer->audio->id = audio_id;
1125 /* Disable the subs only if there are no text streams at all.
1126 Otherwise the stream to display might be chosen later when the comment
1127 packet is encountered and the user used -slang instead of -sid. */
1128 if(!ogg_d->n_text)
1129 demuxer->sub->id = -2;
1130 else if (text_id >= 0) {
1131 demuxer->sub->id = text_id;
1132 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1135 ogg_d->final_granulepos=0;
1136 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1137 if(!s->end_pos)
1138 demuxer->seekable = 0;
1139 else {
1140 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1141 demuxer->movi_end = s->end_pos;
1142 demuxer->seekable = 1;
1143 demux_ogg_scan_stream(demuxer);
1145 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1146 ogg_d->initial_granulepos = 0;
1147 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1149 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":"");
1151 sh_a = demuxer->audio->sh;
1152 if(sh_a)
1153 if(sh_a->format == FOURCC_VORBIS)
1154 fixup_vorbis_wf(sh_a, ogg_d);
1156 return DEMUXER_TYPE_OGG;
1158 err_out:
1159 return 0;
1163 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1164 ogg_demuxer_t* ogg_d;
1165 stream_t *s;
1166 demux_stream_t *ds;
1167 ogg_sync_state* sync;
1168 ogg_stream_state* os;
1169 ogg_page* page;
1170 ogg_packet pack;
1171 int np = 0, id=0;
1173 s = d->stream;
1174 ogg_d = d->priv;
1175 sync = &ogg_d->sync;
1176 page = &ogg_d->page;
1178 /// Find the stream we are working on
1179 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1180 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1181 return 0;
1184 while(1) {
1185 np = 0;
1186 ds = NULL;
1187 /// Try to get some packet from the current page
1188 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1189 /// No packet we go the next page
1190 if(np == 0) {
1191 while(1) {
1192 int pa,len;
1193 char *buf;
1194 ogg_d->pos += ogg_d->last_size;
1195 /// Get the next page from the physical stream
1196 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1197 /// Error : we skip some bytes
1198 if(pa < 0) {
1199 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1200 ogg_d->pos -= pa;
1201 continue;
1203 /// We need more data
1204 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1205 len = stream_read(s,buf,BLOCK_SIZE);
1206 if(len == 0 && s->eof) {
1207 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1208 return 0;
1210 ogg_sync_wrote(sync,len);
1211 } /// Page loop
1212 ogg_d->last_size = pa;
1213 /// Find the page's logical stream
1214 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1215 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1216 return 0;
1218 /// Take the page
1219 if(ogg_stream_pagein(os,page) == 0)
1220 break;
1221 /// Page was invalid => retry
1222 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1223 ogg_d->pos += ogg_d->last_size;
1225 } else /// Packet was corrupted
1226 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1227 } /// Packet loop
1229 /// Is the actual logical stream in use ?
1230 if(id == d->audio->id)
1231 ds = d->audio;
1232 else if(id == d->video->id)
1233 ds = d->video;
1234 else if (ogg_d->subs[id].text)
1235 ds = d->sub;
1237 if(ds) {
1238 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1239 continue; /// Unuseful packet, get another
1240 d->filepos = ogg_d->pos;
1241 return 1;
1244 } /// while(1)
1248 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1249 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1250 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1251 struct MPOpts *opts = demuxer->opts;
1252 demuxer_t *od;
1253 ogg_demuxer_t *ogg_d;
1254 stream_t* s;
1255 uint32_t hdrsizes[3];
1256 demux_packet_t *dp;
1257 sh_audio_t *sh_audio = demuxer->audio->sh;
1258 int np;
1259 uint8_t *extradata = sh_audio->wf + 1;
1260 int i;
1261 unsigned char *p = NULL,*buf;
1262 int plen;
1264 /// Check that the cbSize is big enough for the following reads
1265 if(sh_audio->wf->cbSize < 22+3*4) {
1266 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1267 goto fallback;
1269 /// Get the size of the 3 header packet
1270 extradata += 22;
1271 for (i = 0; i < 3; i++) {
1272 hdrsizes[i] = AV_RL32(extradata);
1273 extradata += 4;
1275 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1277 /// Check the size
1278 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1279 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1280 goto fallback;
1283 // Build the ogg demuxer private datas
1284 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1285 ogg_d->num_sub = 1;
1286 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1287 ogg_d->subs[0].vorbis = 1;
1289 // Init the ogg physical stream
1290 ogg_sync_init(&ogg_d->sync);
1292 // Get the first page of the stream : we assume there only 1 logical stream
1293 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1294 if(np < 0) {
1295 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1296 free(ogg_d);
1297 goto fallback;
1299 // Add some data
1300 plen = ds_get_packet(demuxer->audio,&p);
1301 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1302 memcpy(buf,p,plen);
1303 ogg_sync_wrote(&ogg_d->sync,plen);
1305 // Init the logical stream
1306 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1307 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1308 // Write the page
1309 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1311 // Create the ds_stream and the ogg demuxer
1312 s = new_ds_stream(demuxer->audio);
1313 od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1315 /// Add the header packets in the ogg demuxer audio stream
1316 for (i = 0; i < 3; i++) {
1317 dp = new_demux_packet(hdrsizes[i]);
1318 memcpy(dp->buffer,extradata,hdrsizes[i]);
1319 ds_add_packet(od->audio,dp);
1320 extradata += hdrsizes[i];
1323 // Finish setting up the ogg demuxer
1324 od->priv = ogg_d;
1325 sh_audio = new_sh_audio(od,0);
1326 od->audio->id = 0;
1327 od->video->id = -2;
1328 od->audio->sh = sh_audio;
1329 sh_audio->ds = od->audio;
1330 sh_audio->format = FOURCC_VORBIS;
1331 fixup_vorbis_wf(sh_audio, ogg_d);
1333 /// Return the joined demuxers
1334 return new_demuxers_demuxer(demuxer,od,demuxer);
1336 fallback:
1337 demuxer->audio->id = -2;
1338 return demuxer;
1342 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1343 ogg_demuxer_t* ogg_d = demuxer->priv;
1344 ogg_sync_state* sync = &ogg_d->sync;
1345 ogg_page* page= &ogg_d->page;
1346 ogg_stream_state* oss;
1347 ogg_stream_t* os;
1348 demux_stream_t* ds;
1349 ogg_packet op;
1350 float rate;
1351 int i,sp,first,precision=1,do_seek=1;
1352 vorbis_info* vi = NULL;
1353 int64_t gp = 0, old_gp;
1354 off_t pos, old_pos;
1355 int np;
1356 int is_gp_valid;
1357 float pts;
1358 int is_keyframe;
1359 int samplesize=1;
1360 ogg_int64_t granulepos_orig;
1362 if(demuxer->video->id >= 0) {
1363 ds = demuxer->video;
1364 rate = ogg_d->subs[ds->id].samplerate;
1365 } else {
1366 ds = demuxer->audio;
1367 os = &ogg_d->subs[ds->id];
1368 vi = &(os->vi);
1369 rate = (float)vi->rate;
1370 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1373 os = &ogg_d->subs[ds->id];
1374 oss = &os->stream;
1376 old_gp = os->lastpos;
1377 old_pos = ogg_d->pos;
1379 //calculate the granulepos to seek to
1380 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1381 if(flags & SEEK_FACTOR) {
1382 if (ogg_d->duration > 0)
1383 gp += ogg_d->duration * rel_seek_secs;
1384 else
1385 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1386 } else
1387 gp += rel_seek_secs * rate;
1388 if (gp < 0) gp = 0;
1390 //calculate the filepos to seek to
1391 if(ogg_d->syncpoints) {
1392 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1393 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1396 if(sp >= ogg_d->num_syncpoint) return;
1397 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1398 sp--;
1399 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1400 if (sp > 0 && gp < os->lastpos) sp--;
1401 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1403 pos = ogg_d->syncpoints[sp].page_pos;
1404 precision = 0;
1405 } else {
1406 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1407 if(flags & SEEK_FACTOR)
1408 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1409 else {
1410 if (ogg_d->duration > 0) {
1411 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1412 } else if (os->lastpos > 0) {
1413 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1416 if (pos < 0) pos = 0;
1417 if (pos > (demuxer->movi_end - demuxer->movi_start))
1418 pos = demuxer->movi_end - demuxer->movi_start;
1419 } // if(ogg_d->syncpoints)
1421 while(1) {
1422 if (do_seek) {
1423 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1424 ogg_sync_reset(sync);
1425 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1426 ogg_stream_reset(&ogg_d->subs[i].stream);
1427 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1429 ogg_d->pos = pos;
1430 ogg_d->last_size = 0;
1431 /* we just guess that we reached correct granulepos, in case a
1432 subsequent search occurs before we read a valid granulepos */
1433 os->lastpos = gp;
1434 first = !(ogg_d->syncpoints);
1435 do_seek=0;
1437 ogg_d->pos += ogg_d->last_size;
1438 ogg_d->last_size = 0;
1439 np = ogg_sync_pageseek(sync,page);
1441 if(np < 0)
1442 ogg_d->pos -= np;
1443 if(np <= 0) { // We need more data
1444 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1445 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1446 if(len == 0 && demuxer->stream->eof) {
1447 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1448 return;
1450 ogg_sync_wrote(sync,len);
1451 continue;
1453 ogg_d->last_size = np;
1454 if(ogg_page_serialno(page) != oss->serialno)
1455 continue;
1457 if(ogg_stream_pagein(oss,page) != 0)
1458 continue;
1460 while(1) {
1461 np = ogg_stream_packetout(oss,&op);
1462 if(np < 0)
1463 continue;
1464 else if(np == 0)
1465 break;
1466 if (first) { /* Discard the first packet as it's probably broken,
1467 and we don't have any other means to decide whether it is
1468 complete or not. */
1469 first = 0;
1470 break;
1472 is_gp_valid = (op.granulepos >= 0);
1473 granulepos_orig=op.granulepos;
1474 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1475 if (precision && is_gp_valid) {
1476 precision--;
1477 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1478 //prepare another seek because we are off by more than 1s
1479 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1480 if (pos < 0) pos = 0;
1481 if (pos < demuxer->movi_end - demuxer->movi_start) {
1482 do_seek=1;
1483 break;
1487 if (is_gp_valid && pos > 0 && old_gp > gp
1488 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1489 /* prepare another seek because looking for a syncpoint
1490 destroyed the backward search */
1491 pos = old_pos - 1.5 * (old_pos - pos);
1492 if (pos < 0) pos = 0;
1493 if (pos < demuxer->movi_end - demuxer->movi_start) {
1494 do_seek=1;
1495 break;
1498 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1499 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1500 vo_sub = &ogg_sub;
1501 vo_osd_changed(OSDTYPE_SUBTITLE);
1503 op.granulepos=granulepos_orig;
1504 demux_ogg_add_packet(ds,os,ds->id,&op);
1505 return;
1510 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1514 static void demux_close_ogg(demuxer_t* demuxer) {
1515 ogg_demuxer_t* ogg_d = demuxer->priv;
1516 ogg_stream_t* os = NULL;
1517 int i;
1519 if(!ogg_d)
1520 return;
1522 #ifdef CONFIG_ICONV
1523 subcp_close();
1524 #endif
1526 ogg_sync_clear(&ogg_d->sync);
1527 if(ogg_d->subs)
1529 for (i = 0; i < ogg_d->num_sub; i++)
1531 os = &ogg_d->subs[i];
1532 ogg_stream_clear(&os->stream);
1533 if(os->vi_initialized)
1534 vorbis_info_clear(&os->vi);
1536 free(ogg_d->subs);
1538 if(ogg_d->syncpoints)
1539 free(ogg_d->syncpoints);
1540 if (ogg_d->text_ids)
1541 free(ogg_d->text_ids);
1542 if (ogg_d->text_langs) {
1543 for (i = 0; i < ogg_d->n_text; i++)
1544 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1545 free(ogg_d->text_langs);
1547 free(ogg_d);
1550 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1551 ogg_demuxer_t* ogg_d = demuxer->priv;
1552 ogg_stream_t* os;
1553 float rate;
1555 if(demuxer->video->id >= 0) {
1556 os = &ogg_d->subs[demuxer->video->id];
1557 rate = os->samplerate;
1558 } else {
1559 os = &ogg_d->subs[demuxer->audio->id];
1560 rate = os->vi.rate;
1564 switch(cmd) {
1565 case DEMUXER_CTRL_GET_TIME_LENGTH:
1566 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1567 *(double *)arg=(double)(ogg_d->duration) / rate;
1568 return DEMUXER_CTRL_GUESS;
1570 case DEMUXER_CTRL_GET_PERCENT_POS:
1571 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1572 *(int *)arg=((os->lastpos - ogg_d->initial_granulepos)*100) / ogg_d->duration;
1573 return DEMUXER_CTRL_OK;
1575 default:
1576 return DEMUXER_CTRL_NOTIMPL;
1582 const demuxer_desc_t demuxer_desc_ogg = {
1583 "Ogg demuxer",
1584 "ogg",
1585 "Ogg",
1586 "?",
1588 DEMUXER_TYPE_OGG,
1589 1, // safe autodetect
1590 demux_ogg_open,
1591 demux_ogg_fill_buffer,
1592 NULL,
1593 demux_close_ogg,
1594 demux_ogg_seek,
1595 demux_ogg_control