Fix vf_tcdump's compilation
[mplayer/kovensky.git] / libmpdemux / demux_ogg.c
blobacb783d71ff77d15a280d0f10fa0046fb37aa85b
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 "stream/stream.h"
31 #include "demuxer.h"
32 #include "stheader.h"
33 #include "ffmpeg_files/intreadwrite.h"
34 #include "aviprint.h"
35 #include "demux_mov.h"
36 #include "demux_ogg.h"
38 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
39 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
40 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
42 #ifdef CONFIG_TREMOR
43 #include <tremor/ogg.h>
44 #include <tremor/ivorbiscodec.h>
45 #else
46 #include <ogg/ogg.h>
47 #include <vorbis/codec.h>
48 #endif
50 #ifdef CONFIG_OGGTHEORA
51 #include <theora/theora.h>
52 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
53 #endif
55 #define BLOCK_SIZE 4096
57 /* Theora decoder context : we won't be able to interpret granule positions
58 * without using theora_granule_time with the theora_state of the stream.
59 * This is duplicated in `vd_theora.c'; put this in a common header?
61 #ifdef CONFIG_OGGTHEORA
62 typedef struct theora_struct_st {
63 theora_state st;
64 theora_comment cc;
65 theora_info inf;
66 } theora_struct_t;
67 #endif
69 //// OggDS headers
70 // Header for the new header format
71 typedef struct stream_header_video
73 ogg_int32_t width;
74 ogg_int32_t height;
75 } stream_header_video;
77 typedef struct stream_header_audio
79 ogg_int16_t channels;
80 ogg_int16_t blockalign;
81 ogg_int32_t avgbytespersec;
82 } stream_header_audio;
84 typedef struct __attribute__((__packed__)) stream_header
86 char streamtype[8];
87 char subtype[4];
89 ogg_int32_t size; // size of the structure
91 ogg_int64_t time_unit; // in reference time
92 ogg_int64_t samples_per_unit;
93 ogg_int32_t default_len; // in media time
95 ogg_int32_t buffersize;
96 ogg_int16_t bits_per_sample;
98 ogg_int16_t padding;
100 union
102 // Video specific
103 stream_header_video video;
104 // Audio specific
105 stream_header_audio audio;
106 } sh;
107 } stream_header;
109 /// Our private datas
111 typedef struct ogg_syncpoint {
112 int64_t granulepos;
113 off_t page_pos;
114 } ogg_syncpoint_t;
116 /// A logical stream
117 typedef struct ogg_stream {
118 /// Timestamping stuff
119 float samplerate; /// granulpos 2 time
120 int64_t lastpos;
121 int32_t lastsize;
122 int keyframe_frequency_force;
124 // Logical stream state
125 ogg_stream_state stream;
126 int hdr_packets;
127 int vorbis;
128 int speex;
129 int theora;
130 int flac;
131 int text;
132 int id;
134 vorbis_info vi;
135 int vi_initialized;
137 void *ogg_d;
138 } ogg_stream_t;
140 typedef struct ogg_demuxer {
141 /// Physical stream state
142 ogg_sync_state sync;
143 /// Current page
144 ogg_page page;
145 /// Logical streams
146 ogg_stream_t *subs;
147 int num_sub;
148 ogg_syncpoint_t* syncpoints;
149 int num_syncpoint;
150 off_t pos, last_size;
151 int64_t initial_granulepos;
152 int64_t final_granulepos;
153 int64_t duration;
155 /* Used for subtitle switching. */
156 int n_text;
157 int *text_ids;
158 char **text_langs;
159 } ogg_demuxer_t;
161 #define NUM_VORBIS_HDR_PACKETS 3
163 /// Some defines from OggDS
164 #define PACKET_TYPE_HEADER 0x01
165 #define PACKET_TYPE_BITS 0x07
166 #define PACKET_LEN_BITS01 0xc0
167 #define PACKET_LEN_BITS2 0x02
168 #define PACKET_IS_SYNCPOINT 0x08
170 extern char *dvdsub_lang, *audio_lang;
172 //-------- subtitle support - should be moved to decoder layer, and queue
173 // - subtitles up in demuxer buffer...
175 #include "subreader.h"
176 #include "libvo/sub.h"
177 #define OGG_SUB_MAX_LINE 128
179 static subtitle ogg_sub;
180 //FILE* subout;
182 static void demux_ogg_add_sub(ogg_stream_t *os, ogg_packet *pack)
184 int lcv;
185 char *packet = pack->packet;
187 if (pack->bytes < 4)
188 return;
189 mp_msg(MSGT_DEMUX,MSGL_DBG2,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
190 (unsigned char)packet[0],
191 (unsigned char)packet[1],
192 (unsigned char)packet[2],
193 &packet[3]);
195 if (((unsigned char)packet[0]) == 0x88) { // some subtitle text
196 // Find data start
197 double endpts = MP_NOPTS_VALUE;
198 int32_t duration = 0;
199 int16_t hdrlen = (*packet & PACKET_LEN_BITS01)>>6, i;
200 hdrlen |= (*packet & PACKET_LEN_BITS2) <<1;
201 lcv = 1 + hdrlen;
202 if (pack->bytes < lcv)
203 return;
204 for (i = hdrlen; i > 0; i--) {
205 duration <<= 8;
206 duration |= (unsigned char)packet[i];
208 if (hdrlen > 0 && duration > 0) {
209 float pts;
210 if(pack->granulepos == -1)
211 pack->granulepos = os->lastpos + os->lastsize;
212 pts = (float)pack->granulepos/(float)os->samplerate;
213 endpts = 1.0 + pts + (float)duration/1000.0;
215 sub_clear_text(&ogg_sub, MP_NOPTS_VALUE);
216 sub_add_text(&ogg_sub, &packet[lcv], pack->bytes - lcv, endpts);
219 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg sub lines: %d first: '%s'\n",
220 ogg_sub.lines, ogg_sub.text[0]);
221 #ifdef CONFIG_ICONV
222 subcp_recode(&ogg_sub);
223 #endif
224 vo_sub = &ogg_sub;
225 vo_osd_changed(OSDTYPE_SUBTITLE);
229 // get the logical stream of the current page
230 // fill os if non NULL and return the stream id
231 static int demux_ogg_get_page_stream(ogg_demuxer_t* ogg_d,ogg_stream_state** os) {
232 int id,s_no;
233 ogg_page* page = &ogg_d->page;
235 s_no = ogg_page_serialno(page);
237 for(id= 0; id < ogg_d->num_sub ; id++) {
238 if(s_no == ogg_d->subs[id].stream.serialno)
239 break;
242 if(id == ogg_d->num_sub) {
243 // If we have only one vorbis stream allow the stream id to change
244 // it's normal on radio stream (each song have an different id).
245 // But we (or the codec?) should check that the samplerate, etc
246 // doesn't change (for radio stream it's ok)
247 if(ogg_d->num_sub == 1 && ogg_d->subs[0].vorbis) {
248 ogg_stream_reset(&ogg_d->subs[0].stream);
249 ogg_stream_init(&ogg_d->subs[0].stream,s_no);
250 id = 0;
251 } else
252 return -1;
255 if(os)
256 *os = &ogg_d->subs[id].stream;
258 return id;
262 static unsigned char* demux_ogg_read_packet(ogg_stream_t* os,ogg_packet* pack,float* pts,int* flags, int samplesize) {
263 unsigned char* data = pack->packet;
264 int size = pack->bytes;
266 *pts = MP_NOPTS_VALUE;
267 *flags = 0;
269 if(os->vorbis) {
270 if(*pack->packet & PACKET_TYPE_HEADER)
271 os->hdr_packets++;
272 else
274 vorbis_info *vi;
275 int32_t blocksize = 0;
277 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
278 vi = os->vi_initialized ? &os->vi : NULL;
279 if (vi)
280 blocksize = vorbis_packet_blocksize(vi,pack) / samplesize;
281 // Calculate the timestamp if the packet don't have any
282 if(pack->granulepos == -1) {
283 pack->granulepos = os->lastpos;
284 if(os->lastsize > 0)
285 pack->granulepos += os->lastsize;
286 } else
287 *flags = 1;
288 if (vi)
289 *pts = pack->granulepos / (float)vi->rate;
290 os->lastsize = blocksize;
291 os->lastpos = pack->granulepos;
293 } else if (os->speex) {
294 // whole packet (default)
295 # ifdef CONFIG_OGGTHEORA
296 } else if (os->theora) {
297 /* we pass complete packets to theora, mustn't strip the header! */
298 os->lastsize = 1;
300 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
301 have theora_state st, until all header packets were passed to the
302 decoder. */
303 if (!size || !(*data&0x80))
305 int keyframe_granule_shift=_ilog(os->keyframe_frequency_force-1);
306 int64_t iframemask = (1 << keyframe_granule_shift) - 1;
308 if (pack->granulepos >= 0)
310 os->lastpos = pack->granulepos >> keyframe_granule_shift;
311 os->lastpos += pack->granulepos & iframemask;
312 *flags = (pack->granulepos & iframemask) == 0;
314 else
316 os->lastpos++;
318 pack->granulepos = os->lastpos;
319 *pts = (double)os->lastpos / (double)os->samplerate;
321 #endif /* CONFIG_OGGTHEORA */
322 } else if (os->flac) {
323 /* we pass complete packets to flac, mustn't strip the header! */
324 if (os->flac == 2 && pack->packet[0] != 0xff)
325 return NULL;
326 } else {
327 if(*pack->packet & PACKET_TYPE_HEADER)
328 os->hdr_packets++;
329 else {
330 // Find data start
331 int16_t hdrlen = (*pack->packet & PACKET_LEN_BITS01)>>6;
332 hdrlen |= (*pack->packet & PACKET_LEN_BITS2) <<1;
333 data = pack->packet + 1 + hdrlen;
334 // Calculate the timestamp
335 if(pack->granulepos == -1)
336 pack->granulepos = os->lastpos + (os->lastsize ? os->lastsize : 1);
337 // If we already have a timestamp it can be a syncpoint
338 if(*pack->packet & PACKET_IS_SYNCPOINT)
339 *flags = 1;
340 *pts = pack->granulepos/os->samplerate;
341 // Save the packet length and timestamp
342 os->lastsize = 0;
343 while(hdrlen) {
344 os->lastsize <<= 8;
345 os->lastsize |= pack->packet[hdrlen];
346 hdrlen--;
348 os->lastpos = pack->granulepos;
351 return data;
354 // check if clang has substring from comma separated langlist
355 static int demux_ogg_check_lang(const char *clang, const char *langlist)
357 const char *c;
359 if (!langlist || !*langlist)
360 return 0;
361 while ((c = strchr(langlist, ',')))
363 if (!strncasecmp(clang, langlist, c - langlist))
364 return 1;
365 langlist = &c[1];
367 if (!strncasecmp(clang, langlist, strlen(langlist)))
368 return 1;
369 return 0;
372 /** \brief Change the current subtitle stream and return its ID.
374 \param demuxer The demuxer whose subtitle stream will be changed.
375 \param new_num The number of the new subtitle track. The number must be
376 between 0 and ogg_d->n_text - 1.
378 \returns The Ogg stream number ( = page serial number) of the newly selected
379 track.
381 static int demux_ogg_sub_id(demuxer_t *demuxer, int index)
383 ogg_demuxer_t *ogg_d = demuxer->priv;
384 return (index < 0) ? index : (index >= ogg_d->n_text) ? -1 : ogg_d->text_ids[index];
387 /** \brief Translate the ogg track number into the subtitle number.
388 * \param demuxer The demuxer about whose subtitles we are inquiring.
389 * \param id The ogg track number of the subtitle track.
391 static int demux_ogg_sub_reverse_id(demuxer_t *demuxer, int id) {
392 ogg_demuxer_t *ogg_d = demuxer->priv;
393 int i;
394 for (i = 0; i < ogg_d->n_text; i++)
395 if (ogg_d->text_ids[i] == id) return i;
396 return -1;
399 /// Try to print out comments and also check for LANGUAGE= tag
400 static void demux_ogg_check_comments(demuxer_t *d, ogg_stream_t *os, int id, vorbis_comment *vc)
402 const char *hdr, *val;
403 char **cmt = vc->user_comments;
404 int index, i;
405 ogg_demuxer_t *ogg_d = d->priv;
406 static const struct table {
407 const char *ogg;
408 const char *mp;
409 } table[] = {
410 { "ENCODED_USING", "Software" },
411 { "ENCODER_URL", "Encoder URL" },
412 { "TITLE", "Title" },
413 { "ARTIST", "Artist" },
414 { "COMMENT", "Comments" },
415 { "DATE", "Creation Date" },
416 { "GENRE", "Genre" },
417 { "ALBUM", "Album" },
418 { "TRACKNUMBER", "Track" },
419 { NULL, NULL },
422 while(*cmt)
424 hdr = NULL;
425 if (!strncasecmp(*cmt, "LANGUAGE=", 9))
427 val = *cmt + 9;
428 if (ogg_d->subs[id].text)
429 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
430 else if (id != d->video->id)
431 mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", ogg_d->subs[id].id, val);
432 if (ogg_d->subs[id].text)
433 mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d->subs[id].id, val);
434 // copy this language name into the array
435 index = demux_ogg_sub_reverse_id(d, id);
436 if (index >= 0) {
437 sh_sub_t* sh;
438 // in case of malicious files with more than one lang per track:
439 if (ogg_d->text_langs[index]) free(ogg_d->text_langs[index]);
440 ogg_d->text_langs[index] = strdup(val);
441 sh = d->s_streams[index];
442 if (sh && sh->lang) free(sh->lang);
443 if (sh) sh->lang = strdup(val);
445 // check for -slang if subs are uninitialized yet
446 if (os->text && d->sub->id < 0 && demux_ogg_check_lang(val, dvdsub_lang))
448 d->sub->id = index;
449 d->opts->sub_id = index;
450 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id, val);
452 else
453 hdr = "Language";
455 else {
456 for (i = 0; table[i].ogg; i++)
458 if (!strncasecmp(*cmt, table[i].ogg, strlen(table[i].ogg)) &&
459 (*cmt)[strlen(table[i].ogg)] == '=')
461 hdr = table[i].mp;
462 val = *cmt + strlen(table[i].ogg) + 1;
466 if (hdr)
467 demux_info_add(d, hdr, val);
468 mp_dbg(MSGT_DEMUX, MSGL_DBG2, " %s: %s\n", hdr, val);
469 cmt++;
473 /// Calculate the timestamp and add the packet to the demux stream
474 // return 1 if the packet was added, 0 otherwise
475 static int demux_ogg_add_packet(demux_stream_t* ds,ogg_stream_t* os,int id,ogg_packet* pack) {
476 demuxer_t* d = ds->demuxer;
477 demux_packet_t* dp;
478 unsigned char* data;
479 float pts = 0;
480 int flags = 0;
481 int samplesize = 1;
483 // If packet is an comment header then we try to get comments at first
484 if (pack->bytes >= 7 && !memcmp(pack->packet, "\003vorbis", 7))
486 vorbis_info vi;
487 vorbis_comment vc;
489 vorbis_info_init(&vi);
490 vorbis_comment_init(&vc);
491 vi.rate = 1L; // it's checked by vorbis_synthesis_headerin()
492 if(vorbis_synthesis_headerin(&vi, &vc, pack) == 0) // if no errors
493 demux_ogg_check_comments(d, os, id, &vc);
494 vorbis_comment_clear(&vc);
495 vorbis_info_clear(&vi);
497 if (os->text) {
498 if (id == demux_ogg_sub_id(d, d->sub->id)) // don't want to add subtitles to the demuxer for now
499 demux_ogg_add_sub(os,pack);
500 return 0;
502 if (os->speex) {
503 // discard first two packets, they contain the header and comment
504 if (os->hdr_packets < 2) {
505 os->hdr_packets++;
506 return 0;
508 } else
509 // If packet is an header we jump it except for vorbis and theora
510 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
511 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
512 // handled differently for each and every stream type. The joy! The joy!
513 if(!os->flac && (*pack->packet & PACKET_TYPE_HEADER) &&
514 (ds != d->audio || ((sh_audio_t*)ds->sh)->format != FOURCC_VORBIS || os->hdr_packets >= NUM_VORBIS_HDR_PACKETS ) &&
515 (ds != d->video || (((sh_video_t*)ds->sh)->format != FOURCC_THEORA)))
516 return 0;
518 // For vorbis packet the packet is the data, for other codec we must jump
519 // the header
520 if(ds == d->audio && ((sh_audio_t*)ds->sh)->format == FOURCC_VORBIS) {
521 samplesize = ((sh_audio_t *)ds->sh)->samplesize;
523 data = demux_ogg_read_packet(os,pack,&pts,&flags,samplesize);
524 if (!data)
525 return 0;
527 /// Clear subtitles if necessary (for broken files)
528 if (sub_clear_text(&ogg_sub, pts)) {
529 vo_sub = &ogg_sub;
530 vo_osd_changed(OSDTYPE_SUBTITLE);
532 /// Send the packet
533 dp = new_demux_packet(pack->bytes-(data-pack->packet));
534 memcpy(dp->buffer,data,pack->bytes-(data-pack->packet));
535 dp->pts = pts;
536 dp->flags = flags;
537 ds_add_packet(ds,dp);
538 mp_msg(MSGT_DEMUX,MSGL_DBG2,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
539 dp, ds, pts, dp->len, flags);
540 return 1;
543 /// if -forceidx build a table of all syncpoints to make seeking easier
544 /// otherwise try to get at least the final_granulepos
545 static void demux_ogg_scan_stream(demuxer_t *demuxer)
547 ogg_demuxer_t* ogg_d = demuxer->priv;
548 stream_t *s = demuxer->stream;
549 ogg_sync_state* sync = &ogg_d->sync;
550 ogg_page* page= &ogg_d->page;
551 ogg_stream_state* oss;
552 ogg_stream_t* os;
553 ogg_packet op;
554 int np,sid,p,samplesize=1;
555 off_t pos, last_pos;
556 pos = last_pos = demuxer->movi_start;
558 // Reset the stream
559 stream_seek(s,demuxer->movi_start);
560 ogg_sync_reset(sync);
562 // Get the serial number of the stream we use
563 if(demuxer->video->id >= 0) {
564 sid = demuxer->video->id;
566 else if(demuxer->audio->id >= 0) {
567 sid = demuxer->audio->id;
568 if(((sh_audio_t*)demuxer->audio->sh)->format == FOURCC_VORBIS) {
569 samplesize = ((sh_audio_t*)demuxer->audio->sh)->samplesize;
572 else return;
573 os = &ogg_d->subs[sid];
574 oss = &os->stream;
576 while(1) {
577 np = ogg_sync_pageseek(sync,page);
578 if(np < 0) { // We had to skip some bytes
579 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_ERR,"Bad page sync while building syncpoints table (%d)\n",-np);
580 pos += -np;
581 continue;
583 if(np <= 0) { // We need more data
584 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
585 int len = stream_read(s,buf,BLOCK_SIZE);
586 if(len == 0 && s->eof)
587 break;
588 ogg_sync_wrote(sync,len);
589 continue;
591 // The page is ready
592 //ogg_sync_pageout(sync,page);
593 if(ogg_page_serialno(page) != os->stream.serialno) { // It isn't a page from the stream we want
594 pos += np;
595 continue;
597 if(ogg_stream_pagein(oss,page) != 0) {
598 mp_msg(MSGT_DEMUX,MSGL_ERR,"Pagein error ????\n");
599 pos += np;
600 continue;
602 p = 0;
603 while(ogg_stream_packetout(oss,&op) == 1) {
604 float pts;
605 int flags;
606 demux_ogg_read_packet(os,&op,&pts,&flags,samplesize);
607 if(op.granulepos >= 0) {
608 ogg_d->final_granulepos = op.granulepos;
609 if(ogg_d->initial_granulepos == MP_NOPTS_VALUE && (flags & 1)) {
610 ogg_d->initial_granulepos = op.granulepos;
611 if (index_mode != 2 && ogg_d->pos < demuxer->movi_end-2*270000) {
612 //the 270000 are just a wild guess
613 stream_seek(s,FFMAX(ogg_d->pos,demuxer->movi_end-270000));
614 ogg_sync_reset(sync);
615 continue;
619 if(index_mode == 2 && (flags || (os->vorbis && op.granulepos >= 0))) {
620 if (ogg_d->num_syncpoint > SIZE_MAX / sizeof(ogg_syncpoint_t) - 1) break;
621 ogg_d->syncpoints = realloc_struct(ogg_d->syncpoints,(ogg_d->num_syncpoint+1), sizeof(ogg_syncpoint_t));
622 ogg_d->syncpoints[ogg_d->num_syncpoint].granulepos = op.granulepos;
623 ogg_d->syncpoints[ogg_d->num_syncpoint].page_pos = (ogg_page_continued(page) && p == 0) ? last_pos : pos;
624 ogg_d->num_syncpoint++;
626 p++;
628 if(p > 1 || (p == 1 && ! ogg_page_continued(page)))
629 last_pos = pos;
630 pos += np;
631 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"Building syncpoint table %d%%\r",(int)(pos*100/s->end_pos));
633 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_INFO,"\n");
635 if(index_mode == 2) mp_msg(MSGT_DEMUX,MSGL_V,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d->num_syncpoint);
636 mp_msg(MSGT_DEMUX,MSGL_V,"Ogg stream length (granulepos): %"PRId64"\n",ogg_d->final_granulepos);
638 stream_reset(s);
639 stream_seek(s,demuxer->movi_start);
640 ogg_sync_reset(sync);
641 for(np = 0 ; np < ogg_d->num_sub ; np++) {
642 ogg_stream_reset(&ogg_d->subs[np].stream);
643 ogg_d->subs[np].lastpos = ogg_d->subs[np].lastsize = ogg_d->subs[np].hdr_packets = 0;
647 // Get the first page
648 while(1) {
649 np = ogg_sync_pageout(sync,page);
650 if(np <= 0) { // We need more data
651 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
652 int len = stream_read(s,buf,BLOCK_SIZE);
653 if(len == 0 && s->eof) {
654 mp_msg(MSGT_DEMUX,MSGL_ERR,"EOF while trying to get the first page !!!!\n");
655 break;
658 ogg_sync_wrote(sync,len);
659 continue;
661 demux_ogg_get_page_stream(ogg_d,&oss);
662 ogg_stream_pagein(oss,page);
663 break;
668 static void fixup_vorbis_wf(sh_audio_t *sh, ogg_demuxer_t *od)
670 int i, offset;
671 int ris, init_error = 0;
672 ogg_packet op[3];
673 unsigned char *buf[3];
674 unsigned char *ptr;
675 unsigned int len;
676 ogg_stream_t *os = &od->subs[sh->ds->id];
677 vorbis_comment vc;
679 vorbis_info_init(&os->vi);
680 vorbis_comment_init(&vc);
681 for(i = 0; i < 3; i++) {
682 op[i].bytes = ds_get_packet(sh->ds, &(op[i].packet));
683 mp_msg(MSGT_DEMUX,MSGL_V, "fixup_vorbis_wf: i=%d, size=%ld\n", i, op[i].bytes);
684 if(op[i].bytes < 0) {
685 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i);
686 return;
688 buf[i] = malloc(op[i].bytes);
689 if(!buf[i])
690 return;
691 memcpy(buf[i], op[i].packet, op[i].bytes);
693 op[i].b_o_s = (i==0);
694 ris = vorbis_synthesis_headerin(&os->vi,&vc,&op[i]);
695 if(ris < 0) {
696 init_error = 1;
697 mp_msg(MSGT_DECAUDIO,MSGL_ERR,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i, op[i].bytes, ris);
700 vorbis_comment_clear(&vc);
701 if(!init_error)
702 os->vi_initialized = 1;
704 len = op[0].bytes + op[1].bytes + op[2].bytes;
705 sh->wf = calloc(1, sizeof(WAVEFORMATEX) + len + len/255 + 64);
706 ptr = (unsigned char*) (sh->wf+1);
708 ptr[0] = 2;
709 offset = 1;
710 offset += store_ughvlc(&ptr[offset], op[0].bytes);
711 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 1st len = %u\n", offset);
712 offset += store_ughvlc(&ptr[offset], op[1].bytes);
713 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, offset after 2nd len = %u\n", offset);
714 for(i = 0; i < 3; i++) {
715 mp_msg(MSGT_DEMUX,MSGL_V,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i, op[i].bytes, offset);
716 memcpy(&ptr[offset], buf[i], op[i].bytes);
717 offset += op[i].bytes;
719 sh->wf->cbSize = offset;
720 mp_msg(MSGT_DEMUX,MSGL_V, "demux_ogg, extradata size: %d\n", sh->wf->cbSize);
721 sh->wf = realloc(sh->wf, sizeof(WAVEFORMATEX) + sh->wf->cbSize);
723 if(op[0].bytes >= 29) {
724 unsigned int br;
725 int nombr, minbr, maxbr;
726 ptr = buf[0];
727 sh->channels = ptr[11];
728 sh->samplerate = sh->wf->nSamplesPerSec = AV_RL32(&ptr[12]);
729 maxbr = AV_RL32(&ptr[16]); //max
730 nombr = AV_RL32(&ptr[20]); //nominal
731 minbr = AV_RL32(&ptr[24]); //minimum
733 if(maxbr == -1)
734 maxbr = 0;
735 if(nombr == -1)
736 nombr = 0;
737 if(minbr == -1)
738 minbr = 0;
740 br = maxbr / 8;
741 if(!br)
742 br = nombr / 8;
743 if(!br)
744 br = minbr / 8;
745 sh->wf->nAvgBytesPerSec = br;
746 sh->wf->wBitsPerSample = 16;
747 sh->samplesize = (sh->wf->wBitsPerSample+7)/8;
749 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",
750 sh->channels, sh->samplerate, sh->wf->nAvgBytesPerSec, maxbr, nombr, minbr);
752 free(buf[2]);
753 free(buf[1]);
754 free(buf[0]);
758 /// Open an ogg physical stream
759 // Not static because it's used also in demuxer_avi.c
760 int demux_ogg_open(demuxer_t* demuxer) {
761 ogg_demuxer_t* ogg_d;
762 stream_t *s;
763 char* buf;
764 int np,s_no, n_audio = 0, n_video = 0;
765 int audio_id = -1, video_id = -1, text_id = -1;
766 ogg_sync_state* sync;
767 ogg_page* page;
768 ogg_packet pack;
769 sh_audio_t* sh_a;
770 sh_video_t* sh_v;
772 #ifdef CONFIG_ICONV
773 subcp_open(NULL);
774 #endif
776 s = demuxer->stream;
778 demuxer->priv =
779 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
780 sync = &ogg_d->sync;
781 page = &ogg_d->page;
783 ogg_sync_init(sync);
785 while(1) {
786 /// Try to get a page
787 ogg_d->pos += ogg_d->last_size;
788 np = ogg_sync_pageseek(sync,page);
789 /// Error
790 if(np < 0) {
791 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n");
792 goto err_out;
794 /// Need some more data
795 if(np == 0) {
796 int len;
797 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
798 len = stream_read(s,buf,BLOCK_SIZE);
799 if(len == 0 && s->eof) {
800 goto err_out;
802 ogg_sync_wrote(sync,len);
803 continue;
805 ogg_d->last_size = np;
806 // We got one page now
808 if( ! ogg_page_bos(page) ) { // It's not a beginning page
809 // Header parsing end here, we need to get the page otherwise it will be lost
810 int id = demux_ogg_get_page_stream(ogg_d,NULL);
811 if(id >= 0)
812 ogg_stream_pagein(&ogg_d->subs[id].stream,page);
813 else
814 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page));
815 break;
818 /// Init the data structure needed for a logical stream
819 ogg_d->subs = realloc_struct(ogg_d->subs,ogg_d->num_sub+1,sizeof(ogg_stream_t));
820 memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t));
821 /// Get the stream serial number
822 s_no = ogg_page_serialno(page);
823 ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no);
824 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no);
825 // Take the first page
826 ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page);
827 // Get first packet of the page
828 ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack);
830 // Reset our vars
831 sh_a = NULL;
832 sh_v = NULL;
834 ogg_d->subs[ogg_d->num_sub].ogg_d = ogg_d;
836 // Check for Vorbis
837 if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) {
838 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
839 sh_a->format = FOURCC_VORBIS;
840 ogg_d->subs[ogg_d->num_sub].vorbis = 1;
841 ogg_d->subs[ogg_d->num_sub].id = n_audio;
842 n_audio++;
843 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1);
844 } else if (pack.bytes >= 80 && !strncmp(pack.packet,"Speex", 5)) {
845 sh_a = new_sh_audio_aid(demuxer, ogg_d->num_sub, n_audio);
846 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + pack.bytes);
847 sh_a->format = FOURCC_SPEEX;
848 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(&pack.packet[36]);
849 sh_a->channels = sh_a->wf->nChannels = AV_RL32(&pack.packet[48]);
850 sh_a->wf->wFormatTag = sh_a->format;
851 sh_a->wf->nAvgBytesPerSec = AV_RL32(&pack.packet[52]);
852 sh_a->wf->nBlockAlign = 0;
853 sh_a->wf->wBitsPerSample = 16;
854 sh_a->samplesize = 2;
855 sh_a->wf->cbSize = pack.bytes;
856 memcpy(&sh_a->wf[1], pack.packet, pack.bytes);
858 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate;
859 ogg_d->subs[ogg_d->num_sub].speex = 1;
860 ogg_d->subs[ogg_d->num_sub].id = n_audio;
861 n_audio++;
862 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d->num_sub,n_audio-1);
864 // check for Theora
865 # ifdef CONFIG_OGGTHEORA
866 } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) {
867 int errorCode = 0;
868 theora_info inf;
869 theora_comment cc;
871 theora_info_init (&inf);
872 theora_comment_init (&cc);
874 errorCode = theora_decode_header (&inf, &cc, &pack);
875 if (errorCode)
876 mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n",
877 errorCode);
878 else
880 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
882 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
883 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
884 sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA;
885 sh_v->fps = ((double)inf.fps_numerator)/
886 (double)inf.fps_denominator;
887 sh_v->frametime = ((double)inf.fps_denominator)/
888 (double)inf.fps_numerator;
889 sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width;
890 sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height;
891 sh_v->bih->biBitCount = 24;
892 sh_v->bih->biPlanes = 3;
893 sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) *
894 sh_v->bih->biWidth*sh_v->bih->biHeight);
895 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
896 ogg_d->subs[ogg_d->num_sub].theora = 1;
897 ogg_d->subs[ogg_d->num_sub].keyframe_frequency_force = inf.keyframe_frequency_force;
898 ogg_d->subs[ogg_d->num_sub].id = n_video;
899 n_video++;
900 mp_msg(MSGT_DEMUX,MSGL_INFO,
901 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
902 ogg_d->num_sub,
903 (int)inf.version_major,
904 (int)inf.version_minor,
905 (int)inf.version_subminor,
906 n_video - 1);
907 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
909 theora_comment_clear(&cc);
910 theora_info_clear(&inf);
911 # endif /* CONFIG_OGGTHEORA */
912 } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) {
913 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
914 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
915 ogg_d->subs[ogg_d->num_sub].id = n_audio;
916 n_audio++;
917 ogg_d->subs[ogg_d->num_sub].flac = 1;
918 sh_a->wf = NULL;
919 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);
920 } else if (pack.bytes >= 51 && !strncmp(&pack.packet[1], "FLAC", 4)) {
921 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
922 sh_a->format = mmioFOURCC('f', 'L', 'a', 'C');
923 ogg_d->subs[ogg_d->num_sub].id = n_audio;
924 n_audio++;
925 ogg_d->subs[ogg_d->num_sub].flac = 2;
926 sh_a->wf = calloc(1, sizeof(WAVEFORMATEX) + 34);
927 sh_a->wf->wFormatTag = sh_a->format;
928 sh_a->wf->cbSize = 34;
929 memcpy(&sh_a->wf[1], &pack.packet[17], 34);
930 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d->num_sub,n_audio-1);
932 /// Check for old header
933 } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) {
935 // Old video header
936 if(AV_RL32(pack.packet+96) == 0x05589f80 && pack.bytes >= 184) {
937 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
938 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
939 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
940 sh_v->bih->biCompression=
941 sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69],
942 pack.packet[70],pack.packet[71]);
943 sh_v->frametime = AV_RL64(pack.packet+164)*0.0000001;
944 sh_v->fps = 1/sh_v->frametime;
945 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(pack.packet+176);
946 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(pack.packet+180);
947 sh_v->bih->biBitCount = AV_RL16(pack.packet+182);
948 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
949 sh_v->bih->biPlanes=1;
950 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
952 ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps;
953 ogg_d->subs[ogg_d->num_sub].id = n_video;
954 n_video++;
955 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
956 ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1);
957 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
958 // Old audio header
959 } else if(AV_RL32(pack.packet+96) == 0x05589F81) {
960 unsigned int extra_size;
961 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
962 extra_size = AV_RL16(pack.packet+140);
963 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
964 sh_a->format = sh_a->wf->wFormatTag = AV_RL16(pack.packet+124);
965 sh_a->channels = sh_a->wf->nChannels = AV_RL16(pack.packet+126);
966 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL32(pack.packet+128);
967 sh_a->wf->nAvgBytesPerSec = AV_RL32(pack.packet+132);
968 sh_a->wf->nBlockAlign = AV_RL16(pack.packet+136);
969 sh_a->wf->wBitsPerSample = AV_RL16(pack.packet+138);
970 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
971 sh_a->wf->cbSize = extra_size;
972 if(extra_size > 0)
973 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size);
975 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
976 ogg_d->subs[ogg_d->num_sub].id = n_audio;
977 n_audio++;
978 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);
979 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
980 } else
981 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub);
983 // Check new header
984 } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER &&
985 pack.bytes >= (int)sizeof(stream_header)+1) {
986 stream_header *st = (stream_header*)(pack.packet+1);
987 /// New video header
988 if(strncmp(st->streamtype,"video",5) == 0) {
989 sh_v = new_sh_video_vid(demuxer,ogg_d->num_sub, n_video);
990 sh_v->bih = calloc(1,sizeof(BITMAPINFOHEADER));
991 sh_v->bih->biSize=sizeof(BITMAPINFOHEADER);
992 sh_v->bih->biCompression=
993 sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1],
994 st->subtype[2],st->subtype[3]);
995 sh_v->frametime = AV_RL64(&st->time_unit)*0.0000001;
996 sh_v->fps = 1.0/sh_v->frametime;
997 sh_v->bih->biBitCount = AV_RL16(&st->bits_per_sample);
998 sh_v->disp_w = sh_v->bih->biWidth = AV_RL32(&st->sh.video.width);
999 sh_v->disp_h = sh_v->bih->biHeight = AV_RL32(&st->sh.video.height);
1000 if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME
1001 sh_v->bih->biPlanes=1;
1002 sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight;
1004 ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps;
1005 ogg_d->subs[ogg_d->num_sub].id = n_video;
1006 n_video++;
1007 mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1008 ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1);
1009 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_v->bih,MSGL_V);
1010 /// New audio header
1011 } else if(strncmp(st->streamtype,"audio",5) == 0) {
1012 char buffer[5];
1013 unsigned int extra_size = AV_RL32(&st->size) - sizeof(stream_header);
1014 unsigned int extra_offset = 0;
1016 memcpy(buffer,st->subtype,4);
1017 buffer[4] = '\0';
1019 /* Nasty workaround. stream_header.size seems not to contain the real
1020 size in all cases. There are four extra bytes that are unaccounted
1021 for in front of the real codec initialization data _at least_ for
1022 AAC. So far I've only seen those bytes being all 0, so we can
1023 just skip them here. */
1024 if ((strtol(buffer, NULL, 16) == 0xff) && (extra_size >= 4)) {
1025 extra_size -= 4;
1026 extra_offset = 4;
1029 sh_a = new_sh_audio_aid(demuxer,ogg_d->num_sub, n_audio);
1030 sh_a->wf = calloc(1,sizeof(WAVEFORMATEX)+extra_size);
1031 sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16);
1032 sh_a->channels = sh_a->wf->nChannels = AV_RL16(&st->sh.audio.channels);
1033 sh_a->samplerate = sh_a->wf->nSamplesPerSec = AV_RL64(&st->samples_per_unit);
1034 sh_a->wf->nAvgBytesPerSec = AV_RL32(&st->sh.audio.avgbytespersec);
1035 sh_a->wf->nBlockAlign = AV_RL16(&st->sh.audio.blockalign);
1036 sh_a->wf->wBitsPerSample = AV_RL16(&st->bits_per_sample);
1037 sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8;
1038 sh_a->wf->cbSize = extra_size;
1039 if(extra_size)
1040 memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),((char *)(st+1))+extra_offset,extra_size);
1042 ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels;
1043 ogg_d->subs[ogg_d->num_sub].id = n_audio;
1044 n_audio++;
1045 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);
1046 if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_a->wf,MSGL_V);
1048 /// Check for text (subtitles) header
1049 } else if (strncmp(st->streamtype, "text", 4) == 0) {
1050 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);
1051 ogg_d->subs[ogg_d->num_sub].samplerate= AV_RL64(&st->time_unit)/10;
1052 ogg_d->subs[ogg_d->num_sub].text = 1;
1053 ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text;
1054 if (demuxer->sub->id == ogg_d->n_text)
1055 text_id = ogg_d->num_sub;
1056 new_sh_sub(demuxer, ogg_d->n_text);
1057 ogg_d->n_text++;
1058 ogg_d->text_ids = realloc_struct(ogg_d->text_ids, ogg_d->n_text, sizeof(int));
1059 ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub;
1060 ogg_d->text_langs = realloc_struct(ogg_d->text_langs, ogg_d->n_text, sizeof(char *));
1061 ogg_d->text_langs[ogg_d->n_text - 1] = NULL;
1062 //// Unknown header type
1063 } else
1064 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub);
1065 /// Unknown (invalid ?) header
1066 } else
1067 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub);
1069 if(sh_a || sh_v) {
1070 demux_stream_t* ds = NULL;
1071 if(sh_a) {
1072 // If the audio stream is not defined we took the first one
1073 if(demuxer->audio->id == -1) {
1074 demuxer->audio->id = n_audio - 1;
1075 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1077 /// Is it the stream we want
1078 if(demuxer->audio->id == n_audio - 1) {
1079 demuxer->audio->sh = sh_a;
1080 sh_a->ds = demuxer->audio;
1081 ds = demuxer->audio;
1082 audio_id = ogg_d->num_sub;
1085 if(sh_v) {
1086 /// Also for video
1087 if(demuxer->video->id == -1) {
1088 demuxer->video->id = n_video - 1;
1089 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1091 if(demuxer->video->id == n_video - 1) {
1092 demuxer->video->sh = sh_v;
1093 sh_v->ds = demuxer->video;
1094 ds = demuxer->video;
1095 video_id = ogg_d->num_sub;
1098 /// Add the header packets if the stream isn't seekable
1099 if(ds && !s->end_pos) {
1100 /// Finish the page, otherwise packets will be lost
1101 do {
1102 demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack);
1103 } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1);
1106 ogg_d->num_sub++;
1109 if(!n_video && !n_audio) {
1110 goto err_out;
1113 if(!n_video || video_id < 0)
1114 demuxer->video->id = -2;
1115 else
1116 demuxer->video->id = video_id;
1117 if(!n_audio || audio_id < 0)
1118 demuxer->audio->id = -2;
1119 else
1120 demuxer->audio->id = audio_id;
1121 /* Disable the subs only if there are no text streams at all.
1122 Otherwise the stream to display might be chosen later when the comment
1123 packet is encountered and the user used -slang instead of -sid. */
1124 if(!ogg_d->n_text)
1125 demuxer->sub->id = -2;
1126 else if (text_id >= 0) {
1127 demuxer->sub->id = text_id;
1128 mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id);
1131 ogg_d->final_granulepos=0;
1132 ogg_d->initial_granulepos = MP_NOPTS_VALUE;
1133 if(!s->end_pos)
1134 demuxer->seekable = 0;
1135 else {
1136 demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2)
1137 demuxer->movi_end = s->end_pos;
1138 demuxer->seekable = 1;
1139 demux_ogg_scan_stream(demuxer);
1141 if (ogg_d->initial_granulepos == MP_NOPTS_VALUE)
1142 ogg_d->initial_granulepos = 0;
1143 ogg_d->duration = ogg_d->final_granulepos - ogg_d->initial_granulepos;
1145 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":"");
1147 sh_a = demuxer->audio->sh;
1148 if(sh_a)
1149 if(sh_a->format == FOURCC_VORBIS)
1150 fixup_vorbis_wf(sh_a, ogg_d);
1152 return DEMUXER_TYPE_OGG;
1154 err_out:
1155 return 0;
1159 static int demux_ogg_fill_buffer(demuxer_t *d, demux_stream_t *dsds) {
1160 ogg_demuxer_t* ogg_d;
1161 stream_t *s;
1162 demux_stream_t *ds;
1163 ogg_sync_state* sync;
1164 ogg_stream_state* os;
1165 ogg_page* page;
1166 ogg_packet pack;
1167 int np = 0, id=0;
1169 s = d->stream;
1170 ogg_d = d->priv;
1171 sync = &ogg_d->sync;
1172 page = &ogg_d->page;
1174 /// Find the stream we are working on
1175 if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1176 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n");
1177 return 0;
1180 while(1) {
1181 np = 0;
1182 ds = NULL;
1183 /// Try to get some packet from the current page
1184 while( (np = ogg_stream_packetout(os,&pack)) != 1) {
1185 /// No packet we go the next page
1186 if(np == 0) {
1187 while(1) {
1188 int pa,len;
1189 char *buf;
1190 ogg_d->pos += ogg_d->last_size;
1191 /// Get the next page from the physical stream
1192 while( (pa = ogg_sync_pageseek(sync,page)) <= 0) {
1193 /// Error : we skip some bytes
1194 if(pa < 0) {
1195 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
1196 ogg_d->pos -= pa;
1197 continue;
1199 /// We need more data
1200 buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1201 len = stream_read(s,buf,BLOCK_SIZE);
1202 if(len == 0 && s->eof) {
1203 mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Stream EOF !!!!\n");
1204 return 0;
1206 ogg_sync_wrote(sync,len);
1207 } /// Page loop
1208 ogg_d->last_size = pa;
1209 /// Find the page's logical stream
1210 if( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) {
1211 mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer error : we met an unknown stream\n");
1212 return 0;
1214 /// Take the page
1215 if(ogg_stream_pagein(os,page) == 0)
1216 break;
1217 /// Page was invalid => retry
1218 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg demuxer : got invalid page !!!!!\n");
1219 ogg_d->pos += ogg_d->last_size;
1221 } else /// Packet was corrupted
1222 mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : bad packet in stream %d\n",id);
1223 } /// Packet loop
1225 /// Is the actual logical stream in use ?
1226 if(id == d->audio->id)
1227 ds = d->audio;
1228 else if(id == d->video->id)
1229 ds = d->video;
1230 else if (ogg_d->subs[id].text)
1231 ds = d->sub;
1233 if(ds) {
1234 if(!demux_ogg_add_packet(ds,&ogg_d->subs[id],id,&pack))
1235 continue; /// Unuseful packet, get another
1236 d->filepos = ogg_d->pos;
1237 return 1;
1240 } /// while(1)
1244 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1245 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1246 demuxer_t* init_avi_with_ogg(demuxer_t* demuxer) {
1247 struct MPOpts *opts = demuxer->opts;
1248 demuxer_t *od;
1249 ogg_demuxer_t *ogg_d;
1250 stream_t* s;
1251 uint32_t hdrsizes[3];
1252 demux_packet_t *dp;
1253 sh_audio_t *sh_audio = demuxer->audio->sh;
1254 int np;
1255 uint8_t *extradata = (uint8_t *)(sh_audio->wf + 1);
1256 int i;
1257 unsigned char *p = NULL,*buf;
1258 int plen;
1260 /// Check that the cbSize is big enough for the following reads
1261 if(sh_audio->wf->cbSize < 22+3*4) {
1262 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Initial audio header is too small !!!!!\n");
1263 goto fallback;
1265 /// Get the size of the 3 header packet
1266 extradata += 22;
1267 for (i = 0; i < 3; i++) {
1268 hdrsizes[i] = AV_RL32(extradata);
1269 extradata += 4;
1271 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1273 /// Check the size
1274 if(sh_audio->wf->cbSize < 22+3*4+hdrsizes[0]+hdrsizes[1] + hdrsizes[2]) {
1275 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg : Audio header is too small !!!!!\n");
1276 goto fallback;
1279 // Build the ogg demuxer private datas
1280 ogg_d = calloc(1,sizeof(ogg_demuxer_t));
1281 ogg_d->num_sub = 1;
1282 ogg_d->subs = malloc(sizeof(ogg_stream_t));
1283 ogg_d->subs[0].vorbis = 1;
1285 // Init the ogg physical stream
1286 ogg_sync_init(&ogg_d->sync);
1288 // Get the first page of the stream : we assume there only 1 logical stream
1289 while((np = ogg_sync_pageout(&ogg_d->sync,&ogg_d->page)) <= 0 ) {
1290 if(np < 0) {
1291 mp_msg(MSGT_DEMUX,MSGL_ERR,"AVI Ogg error : Can't init using first stream packets\n");
1292 free(ogg_d);
1293 goto fallback;
1295 // Add some data
1296 plen = ds_get_packet(demuxer->audio,&p);
1297 buf = ogg_sync_buffer(&ogg_d->sync,plen);
1298 memcpy(buf,p,plen);
1299 ogg_sync_wrote(&ogg_d->sync,plen);
1301 // Init the logical stream
1302 mp_msg(MSGT_DEMUX,MSGL_DBG2,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d->page));
1303 ogg_stream_init(&ogg_d->subs[0].stream,ogg_page_serialno(&ogg_d->page));
1304 // Write the page
1305 ogg_stream_pagein(&ogg_d->subs[0].stream,&ogg_d->page);
1307 // Create the ds_stream and the ogg demuxer
1308 s = new_ds_stream(demuxer->audio);
1309 od = new_demuxer(opts, s,DEMUXER_TYPE_OGG,0,-2,-2,NULL);
1311 /// Add the header packets in the ogg demuxer audio stream
1312 for (i = 0; i < 3; i++) {
1313 dp = new_demux_packet(hdrsizes[i]);
1314 memcpy(dp->buffer,extradata,hdrsizes[i]);
1315 ds_add_packet(od->audio,dp);
1316 extradata += hdrsizes[i];
1319 // Finish setting up the ogg demuxer
1320 od->priv = ogg_d;
1321 sh_audio = new_sh_audio(od,0);
1322 od->audio->id = 0;
1323 od->video->id = -2;
1324 od->audio->sh = sh_audio;
1325 sh_audio->ds = od->audio;
1326 sh_audio->format = FOURCC_VORBIS;
1327 fixup_vorbis_wf(sh_audio, ogg_d);
1329 /// Return the joined demuxers
1330 return new_demuxers_demuxer(demuxer,od,demuxer);
1332 fallback:
1333 demuxer->audio->id = -2;
1334 return demuxer;
1338 static void demux_ogg_seek(demuxer_t *demuxer,float rel_seek_secs,float audio_delay,int flags) {
1339 ogg_demuxer_t* ogg_d = demuxer->priv;
1340 ogg_sync_state* sync = &ogg_d->sync;
1341 ogg_page* page= &ogg_d->page;
1342 ogg_stream_state* oss;
1343 ogg_stream_t* os;
1344 demux_stream_t* ds;
1345 ogg_packet op;
1346 float rate;
1347 int i,sp,first,precision=1,do_seek=1;
1348 vorbis_info* vi = NULL;
1349 int64_t gp = 0, old_gp;
1350 off_t pos, old_pos;
1351 int np;
1352 int is_gp_valid;
1353 float pts;
1354 int is_keyframe;
1355 int samplesize=1;
1356 ogg_int64_t granulepos_orig;
1358 if(demuxer->video->id >= 0) {
1359 ds = demuxer->video;
1360 rate = ogg_d->subs[ds->id].samplerate;
1361 } else {
1362 ds = demuxer->audio;
1363 os = &ogg_d->subs[ds->id];
1364 vi = &(os->vi);
1365 rate = (float)vi->rate;
1366 samplesize = ((sh_audio_t*)ds->sh)->samplesize;
1369 os = &ogg_d->subs[ds->id];
1370 oss = &os->stream;
1372 old_gp = os->lastpos;
1373 old_pos = ogg_d->pos;
1375 //calculate the granulepos to seek to
1376 gp = flags & SEEK_ABSOLUTE ? ogg_d->initial_granulepos : os->lastpos;
1377 if(flags & SEEK_FACTOR) {
1378 if (ogg_d->duration > 0)
1379 gp += ogg_d->duration * rel_seek_secs;
1380 else
1381 gp += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) * os->lastpos / ogg_d->pos;
1382 } else
1383 gp += rel_seek_secs * rate;
1384 if (gp < 0) gp = 0;
1386 //calculate the filepos to seek to
1387 if(ogg_d->syncpoints) {
1388 for(sp = 0; sp < ogg_d->num_syncpoint ; sp++) {
1389 if(ogg_d->syncpoints[sp].granulepos >= gp) break;
1392 if(sp >= ogg_d->num_syncpoint) return;
1393 if (sp > 0 && ogg_d->syncpoints[sp].granulepos - gp > gp - ogg_d->syncpoints[sp-1].granulepos)
1394 sp--;
1395 if (ogg_d->syncpoints[sp].granulepos == os->lastpos) {
1396 if (sp > 0 && gp < os->lastpos) sp--;
1397 if (sp < ogg_d->num_syncpoint-1 && gp > os->lastpos) sp++;
1399 pos = ogg_d->syncpoints[sp].page_pos;
1400 precision = 0;
1401 } else {
1402 pos = flags & SEEK_ABSOLUTE ? 0 : ogg_d->pos;
1403 if(flags & SEEK_FACTOR)
1404 pos += (demuxer->movi_end - demuxer->movi_start) * rel_seek_secs;
1405 else {
1406 if (ogg_d->duration > 0) {
1407 pos += rel_seek_secs * (demuxer->movi_end - demuxer->movi_start) / (ogg_d->duration / rate);
1408 } else if (os->lastpos > 0) {
1409 pos += rel_seek_secs * ogg_d->pos / (os->lastpos / rate);
1412 if (pos < 0) pos = 0;
1413 if (pos > (demuxer->movi_end - demuxer->movi_start))
1414 pos = demuxer->movi_end - demuxer->movi_start;
1415 } // if(ogg_d->syncpoints)
1417 while(1) {
1418 if (do_seek) {
1419 stream_seek(demuxer->stream,pos+demuxer->movi_start);
1420 ogg_sync_reset(sync);
1421 for(i = 0 ; i < ogg_d->num_sub ; i++) {
1422 ogg_stream_reset(&ogg_d->subs[i].stream);
1423 ogg_d->subs[i].lastpos = ogg_d->subs[i].lastsize = 0;
1425 ogg_d->pos = pos;
1426 ogg_d->last_size = 0;
1427 /* we just guess that we reached correct granulepos, in case a
1428 subsequent search occurs before we read a valid granulepos */
1429 os->lastpos = gp;
1430 first = !(ogg_d->syncpoints);
1431 do_seek=0;
1433 ogg_d->pos += ogg_d->last_size;
1434 ogg_d->last_size = 0;
1435 np = ogg_sync_pageseek(sync,page);
1437 if(np < 0)
1438 ogg_d->pos -= np;
1439 if(np <= 0) { // We need more data
1440 char* buf = ogg_sync_buffer(sync,BLOCK_SIZE);
1441 int len = stream_read(demuxer->stream,buf,BLOCK_SIZE);
1442 if(len == 0 && demuxer->stream->eof) {
1443 mp_msg(MSGT_DEMUX,MSGL_V,"EOF while trying to seek !!!!\n");
1444 return;
1446 ogg_sync_wrote(sync,len);
1447 continue;
1449 ogg_d->last_size = np;
1450 if(ogg_page_serialno(page) != oss->serialno)
1451 continue;
1453 if(ogg_stream_pagein(oss,page) != 0)
1454 continue;
1456 while(1) {
1457 np = ogg_stream_packetout(oss,&op);
1458 if(np < 0)
1459 continue;
1460 else if(np == 0)
1461 break;
1462 if (first) { /* Discard the first packet as it's probably broken,
1463 and we don't have any other means to decide whether it is
1464 complete or not. */
1465 first = 0;
1466 break;
1468 is_gp_valid = (op.granulepos >= 0);
1469 granulepos_orig=op.granulepos;
1470 demux_ogg_read_packet(os,&op,&pts,&is_keyframe,samplesize);
1471 if (precision && is_gp_valid) {
1472 precision--;
1473 if (abs(gp - op.granulepos) > rate && (op.granulepos != old_gp)) {
1474 //prepare another seek because we are off by more than 1s
1475 pos += (gp - op.granulepos) * (pos - old_pos) / (op.granulepos - old_gp);
1476 if (pos < 0) pos = 0;
1477 if (pos < demuxer->movi_end - demuxer->movi_start) {
1478 do_seek=1;
1479 break;
1483 if (is_gp_valid && pos > 0 && old_gp > gp
1484 && 2 * (old_gp - op.granulepos) < old_gp - gp) {
1485 /* prepare another seek because looking for a syncpoint
1486 destroyed the backward search */
1487 pos = old_pos - 1.5 * (old_pos - pos);
1488 if (pos < 0) pos = 0;
1489 if (pos < demuxer->movi_end - demuxer->movi_start) {
1490 do_seek=1;
1491 break;
1494 if(!precision && (is_keyframe || os->vorbis || os->speex) ) {
1495 if (sub_clear_text(&ogg_sub, MP_NOPTS_VALUE)) {
1496 vo_sub = &ogg_sub;
1497 vo_osd_changed(OSDTYPE_SUBTITLE);
1499 op.granulepos=granulepos_orig;
1500 demux_ogg_add_packet(ds,os,ds->id,&op);
1501 return;
1506 mp_msg(MSGT_DEMUX,MSGL_ERR,"Can't find the good packet :(\n");
1510 static void demux_close_ogg(demuxer_t* demuxer) {
1511 ogg_demuxer_t* ogg_d = demuxer->priv;
1512 ogg_stream_t* os = NULL;
1513 int i;
1515 if(!ogg_d)
1516 return;
1518 #ifdef CONFIG_ICONV
1519 subcp_close();
1520 #endif
1522 ogg_sync_clear(&ogg_d->sync);
1523 if(ogg_d->subs)
1525 for (i = 0; i < ogg_d->num_sub; i++)
1527 os = &ogg_d->subs[i];
1528 ogg_stream_clear(&os->stream);
1529 if(os->vi_initialized)
1530 vorbis_info_clear(&os->vi);
1532 free(ogg_d->subs);
1534 if(ogg_d->syncpoints)
1535 free(ogg_d->syncpoints);
1536 if (ogg_d->text_ids)
1537 free(ogg_d->text_ids);
1538 if (ogg_d->text_langs) {
1539 for (i = 0; i < ogg_d->n_text; i++)
1540 if (ogg_d->text_langs[i]) free(ogg_d->text_langs[i]);
1541 free(ogg_d->text_langs);
1543 free(ogg_d);
1546 static int demux_ogg_control(demuxer_t *demuxer,int cmd, void *arg){
1547 ogg_demuxer_t* ogg_d = demuxer->priv;
1548 ogg_stream_t* os;
1549 float rate;
1551 if(demuxer->video->id >= 0) {
1552 os = &ogg_d->subs[demuxer->video->id];
1553 rate = os->samplerate;
1554 } else {
1555 os = &ogg_d->subs[demuxer->audio->id];
1556 rate = os->vi.rate;
1560 switch(cmd) {
1561 case DEMUXER_CTRL_GET_TIME_LENGTH:
1562 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1563 *(double *)arg=(double)(ogg_d->duration) / rate;
1564 return DEMUXER_CTRL_GUESS;
1566 case DEMUXER_CTRL_GET_PERCENT_POS:
1567 if (ogg_d->duration<=0) return DEMUXER_CTRL_DONTKNOW;
1568 *(int *)arg=((os->lastpos - ogg_d->initial_granulepos)*100) / ogg_d->duration;
1569 return DEMUXER_CTRL_OK;
1571 default:
1572 return DEMUXER_CTRL_NOTIMPL;
1578 const demuxer_desc_t demuxer_desc_ogg = {
1579 "Ogg demuxer",
1580 "ogg",
1581 "Ogg",
1582 "?",
1584 DEMUXER_TYPE_OGG,
1585 1, // safe autodetect
1586 demux_ogg_open,
1587 demux_ogg_fill_buffer,
1588 NULL,
1589 demux_close_ogg,
1590 demux_ogg_seek,
1591 demux_ogg_control