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