demux_mkv: Make seeks more precise in some cases
[mplayer/glamo.git] / libmpdemux / demux_ogg.c
blobaf730bb712c04cb42a7a1aaa7e151d8dc8af90a9
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 "libavutil/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 final_granulepos;
151 /* Used for subtitle switching. */
152 int n_text;
153 int *text_ids;
154 char **text_langs;
155 } ogg_demuxer_t;
157 #define NUM_VORBIS_HDR_PACKETS 3
159 /// Some defines from OggDS
160 #define PACKET_TYPE_HEADER 0x01
161 #define PACKET_TYPE_BITS 0x07
162 #define PACKET_LEN_BITS01 0xc0
163 #define PACKET_LEN_BITS2 0x02
164 #define PACKET_IS_SYNCPOINT 0x08
166 extern char *dvdsub_lang, *audio_lang;
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 static 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 d->opts->sub_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 static 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 struct MPOpts *opts = demuxer->opts;
1237 demuxer_t *od;
1238 ogg_demuxer_t *ogg_d;
1239 stream_t* s;
1240 uint32_t hdrsizes[3];
1241 demux_packet_t *dp;
1242 sh_audio_t *sh_audio = demuxer->audio->sh;
1243 int np;
1244 uint8_t *extradata = sh_audio->wf + 1;
1245 int i;
1246 unsigned char *p = NULL,*buf;
1247 int plen;
1249 /// Check that the cbSize is big enough for the following reads
1250 if(sh_audio->wf->cbSize < 22+3*4) {
1251 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1252 goto fallback;
1254 /// Get the size of the 3 header packet
1255 extradata += 22;
1256 for (i = 0; i < 3; i++) {
1257 hdrsizes[i] = AV_RL32(extradata);
1258 extradata += 4;
1260 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1262 /// Check the size
1263 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1264 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1265 goto fallback;
1268 // Build the ogg demuxer private datas
1269 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1270 ogg_d->num_sub = 1;
1271 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1272 ogg_d->subs[0].vorbis = 1;
1274 // Init the ogg physical stream
1275 ogg_sync_init(&ogg_d->sync);
1277 // Get the first page of the stream : we assume there only 1 logical stream
1278 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1279 if(np < 0) {
1280 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1281 free(ogg_d);
1282 goto fallback;
1284 // Add some data
1285 plen = ds_get_packet(demuxer->audio,&p);
1286 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1287 memcpy(buf,p,plen);
1288 ogg_sync_wrote(&ogg_d->sync,plen);
1290 // Init the logical stream
1291 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1292 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1293 // Write the page
1294 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1296 // Create the ds_stream and the ogg demuxer
1297 s = new_ds_stream(demuxer->audio);
1298 od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1300 /// Add the header packets in the ogg demuxer audio stream
1301 for (i = 0; i < 3; i++) {
1302 dp = new_demux_packet(hdrsizes[i]);
1303 memcpy(dp->buffer,extradata,hdrsizes[i]);
1304 ds_add_packet(od->audio,dp);
1305 extradata += hdrsizes[i];
1308 // Finish setting up the ogg demuxer
1309 od->priv = ogg_d;
1310 sh_audio = new_sh_audio(od,0);
1311 od->audio->id = 0;
1312 od->video->id = -2;
1313 od->audio->sh = sh_audio;
1314 sh_audio->ds = od->audio;
1315 sh_audio->format = FOURCC_VORBIS;
1316 fixup_vorbis_wf(sh_audio, ogg_d);
1318 /// Return the joined demuxers
1319 return new_demuxers_demuxer(demuxer,od,demuxer);
1321 fallback:
1322 demuxer->audio->id = -2;
1323 return demuxer;
1327 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1328 ogg_demuxer_t* ogg_d = demuxer->priv;
1329 ogg_sync_state* sync = &ogg_d->sync;
1330 ogg_page* page= &ogg_d->page;
1331 ogg_stream_state* oss;
1332 ogg_stream_t* os;
1333 demux_stream_t* ds;
1334 ogg_packet op;
1335 float rate;
1336 int i,sp,first,precision=1,do_seek=1;
1337 vorbis_info* vi = NULL;
1338 int64_t gp = 0, old_gp;
1339 off_t pos, old_pos;
1340 int np;
1341 int is_gp_valid;
1342 float pts;
1343 int is_keyframe;
1344 int samplesize=1;
1345 ogg_int64_t granulepos_orig;
1347 if(demuxer->video->id >= 0) {
1348 ds = demuxer->video;
1349 rate = ogg_d->subs[ds->id].samplerate;
1350 } else {
1351 ds = demuxer->audio;
1352 os = &ogg_d->subs[ds->id];
1353 vi = &(os->vi);
1354 rate = (float)vi->rate;
1355 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1358 os = &ogg_d->subs[ds->id];
1359 oss = &os->stream;
1361 old_gp = os->lastpos;
1362 old_pos = ogg_d->pos;
1364 //calculate the granulepos to seek to
1365 gp = flags & SEEK_ABSOLUTE ? 0 : os->lastpos;
1366 if(flags & SEEK_FACTOR) {
1367 if (ogg_d->final_granulepos > 0)
1368 gp += ogg_d->final_granulepos * rel_seek_secs;
1369 else
1370 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1371 } else
1372 gp += rel_seek_secs * rate;
1373 if (gp < 0) gp = 0;
1375 //calculate the filepos to seek to
1376 if(ogg_d->syncpoints) {
1377 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1378 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1381 if(sp >= ogg_d->num_syncpoint) return;
1382 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1383 sp--;
1384 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1385 if (sp > 0 && gp < os->lastpos) sp--;
1386 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1388 pos = ogg_d->syncpoints[sp].page_pos;
1389 precision = 0;
1390 } else {
1391 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1392 if(flags & SEEK_FACTOR)
1393 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1394 else {
1395 if (ogg_d->final_granulepos > 0) {
1396 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->final_granulepos / rate);
1397 } else if (os->lastpos > 0) {
1398 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1401 if (pos < 0) pos = 0;
1402 if (pos > (demuxer->movi_end - demuxer->movi_start))
1403 pos = demuxer->movi_end - demuxer->movi_start;
1404 } // if(ogg_d->syncpoints)
1406 while(1) {
1407 if (do_seek) {
1408 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1409 ogg_sync_reset(sync);
1410 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1411 ogg_stream_reset(&ogg_d->subs[i].stream);
1412 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1414 ogg_d->pos = pos;
1415 ogg_d->last_size = 0;
1416 /* we just guess that we reached correct granulepos, in case a
1417 subsequent search occurs before we read a valid granulepos */
1418 os->lastpos = gp;
1419 first = !(ogg_d->syncpoints);
1420 do_seek=0;
1422 ogg_d->pos += ogg_d->last_size;
1423 ogg_d->last_size = 0;
1424 np = ogg_sync_pageseek(sync,page);
1426 if(np < 0)
1427 ogg_d->pos -= np;
1428 if(np <= 0) { // We need more data
1429 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1430 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1431 if(len == 0 && demuxer->stream->eof) {
1432 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1433 return;
1435 ogg_sync_wrote(sync,len);
1436 continue;
1438 ogg_d->last_size = np;
1439 if(ogg_page_serialno(page) != oss->serialno)
1440 continue;
1442 if(ogg_stream_pagein(oss,page) != 0)
1443 continue;
1445 while(1) {
1446 np = ogg_stream_packetout(oss,&op);
1447 if(np < 0)
1448 continue;
1449 else if(np == 0)
1450 break;
1451 if (first) { /* Discard the first packet as it's probably broken,
1452 and we don't have any other means to decide whether it is
1453 complete or not. */
1454 first = 0;
1455 break;
1457 is_gp_valid = (op.granulepos >= 0);
1458 granulepos_orig=op.granulepos;
1459 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1460 if (precision && is_gp_valid) {
1461 precision--;
1462 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1463 //prepare another seek because we are off by more than 1s
1464 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1465 if (pos < 0) pos = 0;
1466 if (pos < demuxer->movi_end - demuxer->movi_start) {
1467 do_seek=1;
1468 break;
1472 if (is_gp_valid && pos > 0 && old_gp > gp
1473 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1474 /* prepare another seek because looking for a syncpoint
1475 destroyed the backward search */
1476 pos = old_pos - 1.5 * (old_pos - pos);
1477 if (pos < 0) pos = 0;
1478 if (pos < demuxer->movi_end - demuxer->movi_start) {
1479 do_seek=1;
1480 break;
1483 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1484 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1485 vo_sub = &ogg_sub;
1486 vo_osd_changed(OSDTYPE_SUBTITLE);
1488 op.granulepos=granulepos_orig;
1489 demux_ogg_add_packet(ds,os,ds->id,&op);
1490 return;
1495 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1499 static void demux_close_ogg(demuxer_t* demuxer) {
1500 ogg_demuxer_t* ogg_d = demuxer->priv;
1501 ogg_stream_t* os = NULL;
1502 int i;
1504 if(!ogg_d)
1505 return;
1507 #ifdef CONFIG_ICONV
1508 subcp_close();
1509 #endif
1511 ogg_sync_clear(&ogg_d->sync);
1512 if(ogg_d->subs)
1514 for (i = 0; i < ogg_d->num_sub; i++)
1516 os = &ogg_d->subs[i];
1517 ogg_stream_clear(&os->stream);
1518 if(os->vi_initialized)
1519 vorbis_info_clear(&os->vi);
1521 free(ogg_d->subs);
1523 if(ogg_d->syncpoints)
1524 free(ogg_d->syncpoints);
1525 if (ogg_d->text_ids)
1526 free(ogg_d->text_ids);
1527 if (ogg_d->text_langs) {
1528 for (i = 0; i < ogg_d->n_text; i++)
1529 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1530 free(ogg_d->text_langs);
1532 free(ogg_d);
1535 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1536 ogg_demuxer_t* ogg_d = demuxer->priv;
1537 ogg_stream_t* os;
1538 float rate;
1540 if(demuxer->video->id >= 0) {
1541 os = &ogg_d->subs[demuxer->video->id];
1542 rate = os->samplerate;
1543 } else {
1544 os = &ogg_d->subs[demuxer->audio->id];
1545 rate = os->vi.rate;
1549 switch(cmd) {
1550 case DEMUXER_CTRL_GET_TIME_LENGTH:
1551 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1552 *(double *)arg=(double)ogg_d->final_granulepos / rate;
1553 return DEMUXER_CTRL_GUESS;
1555 case DEMUXER_CTRL_GET_PERCENT_POS:
1556 if (ogg_d->final_granulepos<=0) return DEMUXER_CTRL_DONTKNOW;
1557 *(int *)arg=(os->lastpos*100) / ogg_d->final_granulepos;
1558 return DEMUXER_CTRL_OK;
1560 default:
1561 return DEMUXER_CTRL_NOTIMPL;
1567 const demuxer_desc_t demuxer_desc_ogg = {
1568 "Ogg demuxer",
1569 "ogg",
1570 "Ogg",
1571 "?",
1573 DEMUXER_TYPE_OGG,
1574 1, // safe autodetect
1575 demux_ogg_open,
1576 demux_ogg_fill_buffer,
1577 NULL,
1578 demux_close_ogg,
1579 demux_ogg_seek,
1580 demux_ogg_control