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.
30 #include "stream/stream.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')
40 #include <tremor/ogg.h>
41 #include <tremor/ivorbiscodec.h>
44 #include <vorbis/codec.h>
47 #ifdef CONFIG_OGGTHEORA
48 #include <theora/theora.h>
49 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
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
{
67 // Header for the new header format
68 typedef struct stream_header_video
72 } stream_header_video
;
74 typedef struct stream_header_audio
77 ogg_int16_t blockalign
;
78 ogg_int32_t avgbytespersec
;
79 } stream_header_audio
;
81 typedef struct __attribute__((__packed__
)) stream_header
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
;
100 stream_header_video video
;
102 stream_header_audio audio
;
106 /// Our private datas
108 typedef struct ogg_syncpoint
{
114 typedef struct ogg_stream
{
115 /// Timestamping stuff
116 float samplerate
; /// granulpos 2 time
119 int keyframe_frequency_force
;
121 // Logical stream state
122 ogg_stream_state stream
;
137 typedef struct ogg_demuxer
{
138 /// Physical stream state
145 ogg_syncpoint_t
* syncpoints
;
147 off_t pos
, last_size
;
148 int64_t final_granulepos
;
150 /* Used for subtitle switching. */
156 #define NUM_VORBIS_HDR_PACKETS 3
158 /// Some defines from OggDS
159 #define PACKET_TYPE_HEADER 0x01
160 #define PACKET_TYPE_BITS 0x07
161 #define PACKET_LEN_BITS01 0xc0
162 #define PACKET_LEN_BITS2 0x02
163 #define PACKET_IS_SYNCPOINT 0x08
165 extern char *dvdsub_lang
, *audio_lang
;
166 extern int dvdsub_id
;
168 //-------- subtitle support - should be moved to decoder layer, and queue
169 // - subtitles up in demuxer buffer...
171 #include "subreader.h"
172 #include "libvo/sub.h"
173 #define OGG_SUB_MAX_LINE 128
175 static subtitle ogg_sub
;
178 void demux_ogg_add_sub (ogg_stream_t
* os
,ogg_packet
* pack
) {
180 char *packet
= pack
->packet
;
184 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
185 (unsigned char)packet
[0],
186 (unsigned char)packet
[1],
187 (unsigned char)packet
[2],
190 if (((unsigned char)packet
[0]) == 0x88) { // some subtitle text
192 double endpts
= MP_NOPTS_VALUE
;
193 int32_t duration
= 0;
194 int16_t hdrlen
= (*packet
& PACKET_LEN_BITS01
)>>6, i
;
195 hdrlen
|= (*packet
& PACKET_LEN_BITS2
) <<1;
197 if (pack
->bytes
< lcv
)
199 for (i
= hdrlen
; i
> 0; i
--) {
201 duration
|= (unsigned char)packet
[i
];
203 if (hdrlen
> 0 && duration
> 0) {
205 if(pack
->granulepos
== -1)
206 pack
->granulepos
= os
->lastpos
+ os
->lastsize
;
207 pts
= (float)pack
->granulepos
/(float)os
->samplerate
;
208 endpts
= 1.0 + pts
+ (float)duration
/1000.0;
210 sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
);
211 sub_add_text(&ogg_sub
, &packet
[lcv
], pack
->bytes
- lcv
, endpts
);
214 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg sub lines: %d first: '%s'\n",
215 ogg_sub
.lines
, ogg_sub
.text
[0]);
217 subcp_recode(&ogg_sub
);
220 vo_osd_changed(OSDTYPE_SUBTITLE
);
224 // get the logical stream of the current page
225 // fill os if non NULL and return the stream id
226 static int demux_ogg_get_page_stream(ogg_demuxer_t
* ogg_d
,ogg_stream_state
** os
) {
228 ogg_page
* page
= &ogg_d
->page
;
230 s_no
= ogg_page_serialno(page
);
232 for(id
= 0; id
< ogg_d
->num_sub
; id
++) {
233 if(s_no
== ogg_d
->subs
[id
].stream
.serialno
)
237 if(id
== ogg_d
->num_sub
) {
238 // If we have only one vorbis stream allow the stream id to change
239 // it's normal on radio stream (each song have an different id).
240 // But we (or the codec?) should check that the samplerate, etc
241 // doesn't change (for radio stream it's ok)
242 if(ogg_d
->num_sub
== 1 && ogg_d
->subs
[0].vorbis
) {
243 ogg_stream_reset(&ogg_d
->subs
[0].stream
);
244 ogg_stream_init(&ogg_d
->subs
[0].stream
,s_no
);
251 *os
= &ogg_d
->subs
[id
].stream
;
257 static unsigned char* demux_ogg_read_packet(ogg_stream_t
* os
,ogg_packet
* pack
,float* pts
,int* flags
, int samplesize
) {
258 unsigned char* data
= pack
->packet
;
264 if(*pack
->packet
& PACKET_TYPE_HEADER
)
266 else if (os
->vi_initialized
)
271 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
273 blocksize
= vorbis_packet_blocksize(vi
,pack
) / samplesize
;
274 // Calculate the timestamp if the packet don't have any
275 if(pack
->granulepos
== -1) {
276 pack
->granulepos
= os
->lastpos
;
278 pack
->granulepos
+= os
->lastsize
;
280 *pts
= pack
->granulepos
/ (float)vi
->rate
;
281 os
->lastsize
= blocksize
;
282 os
->lastpos
= pack
->granulepos
;
284 } else if (os
->speex
) {
285 // whole packet (default)
286 # ifdef CONFIG_OGGTHEORA
287 } else if (os
->theora
) {
288 /* we pass complete packets to theora, mustn't strip the header! */
291 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
292 have theora_state st, until all header packets were passed to the
296 int keyframe_granule_shift
=_ilog(os
->keyframe_frequency_force
-1);
297 int64_t iframemask
= (1 << keyframe_granule_shift
) - 1;
299 if (pack
->granulepos
>= 0)
301 os
->lastpos
= pack
->granulepos
>> keyframe_granule_shift
;
302 os
->lastpos
+= pack
->granulepos
& iframemask
;
303 *flags
= (pack
->granulepos
& iframemask
) == 0;
309 pack
->granulepos
= os
->lastpos
;
310 *pts
= (double)os
->lastpos
/ (double)os
->samplerate
;
312 #endif /* CONFIG_OGGTHEORA */
313 } else if (os
->flac
) {
314 /* we pass complete packets to flac, mustn't strip the header! */
315 if (os
->flac
== 2 && pack
->packet
[0] != 0xff)
318 if(*pack
->packet
& PACKET_TYPE_HEADER
)
322 int16_t hdrlen
= (*pack
->packet
& PACKET_LEN_BITS01
)>>6;
323 hdrlen
|= (*pack
->packet
& PACKET_LEN_BITS2
) <<1;
324 data
= pack
->packet
+ 1 + hdrlen
;
325 // Calculate the timestamp
326 if(pack
->granulepos
== -1)
327 pack
->granulepos
= os
->lastpos
+ (os
->lastsize
? os
->lastsize
: 1);
328 // If we already have a timestamp it can be a syncpoint
329 if(*pack
->packet
& PACKET_IS_SYNCPOINT
)
331 *pts
= pack
->granulepos
/os
->samplerate
;
332 // Save the packet length and timestamp
336 os
->lastsize
|= pack
->packet
[hdrlen
];
339 os
->lastpos
= pack
->granulepos
;
345 // check if clang has substring from comma separated langlist
346 static int demux_ogg_check_lang(const char *clang
, const char *langlist
)
350 if (!langlist
|| !*langlist
)
352 while ((c
= strchr(langlist
, ',')))
354 if (!strncasecmp(clang
, langlist
, c
- langlist
))
358 if (!strncasecmp(clang
, langlist
, strlen(langlist
)))
363 static int demux_ogg_sub_reverse_id(demuxer_t
*demuxer
, int id
);
365 /// Try to print out comments and also check for LANGUAGE= tag
366 static void demux_ogg_check_comments(demuxer_t
*d
, ogg_stream_t
*os
, int id
, vorbis_comment
*vc
)
368 const char *hdr
, *val
;
369 char **cmt
= vc
->user_comments
;
371 ogg_demuxer_t
*ogg_d
= d
->priv
;
372 static const struct table
{
376 { "ENCODED_USING", "Software" },
377 { "ENCODER_URL", "Encoder URL" },
378 { "TITLE", "Title" },
379 { "ARTIST", "Artist" },
380 { "COMMENT", "Comments" },
381 { "DATE", "Creation Date" },
382 { "GENRE", "Genre" },
383 { "ALBUM", "Album" },
384 { "TRACKNUMBER", "Track" },
391 if (!strncasecmp(*cmt
, "LANGUAGE=", 9))
394 if (ogg_d
->subs
[id
].text
)
395 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_SID_%d_LANG=%s\n", ogg_d
->subs
[id
].id
, val
);
396 else if (id
!= d
->video
->id
)
397 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_AID_%d_LANG=%s\n", ogg_d
->subs
[id
].id
, val
);
398 if (ogg_d
->subs
[id
].text
)
399 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d
->subs
[id
].id
, val
);
400 // copy this language name into the array
401 index
= demux_ogg_sub_reverse_id(d
, id
);
404 // in case of malicious files with more than one lang per track:
405 if (ogg_d
->text_langs
[index
]) free(ogg_d
->text_langs
[index
]);
406 ogg_d
->text_langs
[index
] = strdup(val
);
407 sh
= d
->s_streams
[index
];
408 if (sh
&& sh
->lang
) free(sh
->lang
);
409 if (sh
) sh
->lang
= strdup(val
);
411 // check for -slang if subs are uninitialized yet
412 if (os
->text
&& d
->sub
->id
< 0 && demux_ogg_check_lang(val
, dvdsub_lang
))
416 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id
, val
);
422 for (i
= 0; table
[i
].ogg
; i
++)
424 if (!strncasecmp(*cmt
, table
[i
].ogg
, strlen(table
[i
].ogg
)) &&
425 (*cmt
)[strlen(table
[i
].ogg
)] == '=')
428 val
= *cmt
+ strlen(table
[i
].ogg
) + 1;
433 demux_info_add(d
, hdr
, val
);
434 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, " %s: %s\n", hdr
, val
);
439 /// Calculate the timestamp and add the packet to the demux stream
440 // return 1 if the packet was added, 0 otherwise
441 static int demux_ogg_add_packet(demux_stream_t
* ds
,ogg_stream_t
* os
,int id
,ogg_packet
* pack
) {
442 demuxer_t
* d
= ds
->demuxer
;
449 // If packet is an comment header then we try to get comments at first
450 if (pack
->bytes
>= 7 && !memcmp(pack
->packet
, "\003vorbis", 7))
455 vorbis_info_init(&vi
);
456 vorbis_comment_init(&vc
);
457 vi
.rate
= 1L; // it's checked by vorbis_synthesis_headerin()
458 if(vorbis_synthesis_headerin(&vi
, &vc
, pack
) == 0) // if no errors
459 demux_ogg_check_comments(d
, os
, id
, &vc
);
460 vorbis_comment_clear(&vc
);
461 vorbis_info_clear(&vi
);
464 if (id
== demux_ogg_sub_id(d
, d
->sub
->id
)) // don't want to add subtitles to the demuxer for now
465 demux_ogg_add_sub(os
,pack
);
469 // discard first two packets, they contain the header and comment
470 if (os
->hdr_packets
< 2) {
475 // If packet is an header we jump it except for vorbis and theora
476 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
477 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
478 // handled differently for each and every stream type. The joy! The joy!
479 if(!os
->flac
&& (*pack
->packet
& PACKET_TYPE_HEADER
) &&
480 (ds
!= d
->audio
|| ((sh_audio_t
*)ds
->sh
)->format
!= FOURCC_VORBIS
|| os
->hdr_packets
>= NUM_VORBIS_HDR_PACKETS
) &&
481 (ds
!= d
->video
|| (((sh_video_t
*)ds
->sh
)->format
!= FOURCC_THEORA
)))
484 // For vorbis packet the packet is the data, for other codec we must jump
486 if(ds
== d
->audio
&& ((sh_audio_t
*)ds
->sh
)->format
== FOURCC_VORBIS
) {
487 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
489 data
= demux_ogg_read_packet(os
,pack
,&pts
,&flags
,samplesize
);
493 /// Clear subtitles if necessary (for broken files)
494 if (sub_clear_text(&ogg_sub
, pts
)) {
496 vo_osd_changed(OSDTYPE_SUBTITLE
);
499 dp
= new_demux_packet(pack
->bytes
-(data
-pack
->packet
));
500 memcpy(dp
->buffer
,data
,pack
->bytes
-(data
-pack
->packet
));
503 ds_add_packet(ds
,dp
);
504 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
505 dp
, ds
, pts
, dp
->len
, flags
);
509 /// if -forceidx build a table of all syncpoints to make seeking easier
510 /// otherwise try to get at least the final_granulepos
511 void demux_ogg_scan_stream(demuxer_t
* demuxer
) {
512 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
513 stream_t
*s
= demuxer
->stream
;
514 ogg_sync_state
* sync
= &ogg_d
->sync
;
515 ogg_page
* page
= &ogg_d
->page
;
516 ogg_stream_state
* oss
;
519 int np
,sid
,p
,samplesize
=1;
521 pos
= last_pos
= demuxer
->movi_start
;
524 if(index_mode
== 2) {
525 stream_seek(s
,demuxer
->movi_start
);
527 //the 270000 are just a wild guess
528 stream_seek(s
,FFMAX(ogg_d
->pos
,demuxer
->movi_end
-270000));
530 ogg_sync_reset(sync
);
532 // Get the serial number of the stream we use
533 if(demuxer
->video
->id
>= 0) {
534 sid
= demuxer
->video
->id
;
536 else if(demuxer
->audio
->id
>= 0) {
537 sid
= demuxer
->audio
->id
;
538 if(((sh_audio_t
*)demuxer
->audio
->sh
)->format
== FOURCC_VORBIS
) {
539 samplesize
= ((sh_audio_t
*)demuxer
->audio
->sh
)->samplesize
;
543 os
= &ogg_d
->subs
[sid
];
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
);
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
)
558 ogg_sync_wrote(sync
,len
);
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
567 if(ogg_stream_pagein(oss
,page
) != 0) {
568 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Pagein error ????\n");
573 while(ogg_stream_packetout(oss
,&op
) == 1) {
576 demux_ogg_read_packet(os
,&op
,&pts
,&flags
,samplesize
);
577 if(op
.granulepos
>= 0) ogg_d
->final_granulepos
= op
.granulepos
;
578 if(index_mode
== 2 && (flags
|| (os
->vorbis
&& op
.granulepos
>= 0))) {
579 if (ogg_d
->num_syncpoint
> SIZE_MAX
/ sizeof(ogg_syncpoint_t
) - 1) break;
580 ogg_d
->syncpoints
= realloc_struct(ogg_d
->syncpoints
,(ogg_d
->num_syncpoint
+1), sizeof(ogg_syncpoint_t
));
581 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].granulepos
= op
.granulepos
;
582 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].page_pos
= (ogg_page_continued(page
) && p
== 0) ? last_pos
: pos
;
583 ogg_d
->num_syncpoint
++;
587 if(p
> 1 || (p
== 1 && ! ogg_page_continued(page
)))
590 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_INFO
,"Building syncpoint table %d%%\r",(int)(pos
*100/s
->end_pos
));
592 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_INFO
,"\n");
594 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_V
,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d
->num_syncpoint
);
595 mp_msg(MSGT_DEMUX
,MSGL_V
,"Ogg stream length (granulepos): %"PRId64
"\n",ogg_d
->final_granulepos
);
598 stream_seek(s
,demuxer
->movi_start
);
599 ogg_sync_reset(sync
);
600 for(np
= 0 ; np
< ogg_d
->num_sub
; np
++) {
601 ogg_stream_reset(&ogg_d
->subs
[np
].stream
);
602 ogg_d
->subs
[np
].lastpos
= ogg_d
->subs
[np
].lastsize
= ogg_d
->subs
[np
].hdr_packets
= 0;
606 // Get the first page
608 np
= ogg_sync_pageout(sync
,page
);
609 if(np
<= 0) { // We need more data
610 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
611 int len
= stream_read(s
,buf
,BLOCK_SIZE
);
612 if(len
== 0 && s
->eof
) {
613 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"EOF while trying to get the first page !!!!\n");
617 ogg_sync_wrote(sync
,len
);
620 demux_ogg_get_page_stream(ogg_d
,&oss
);
621 ogg_stream_pagein(oss
,page
);
627 void print_wave_header(WAVEFORMATEX
*h
, int verbose_level
);
628 void print_video_header(BITMAPINFOHEADER
*h
, int verbose_level
);
630 /* defined in demux_mov.c */
631 unsigned int store_ughvlc(unsigned char *s
, unsigned int v
);
633 /** \brief Change the current subtitle stream and return its ID.
635 \param demuxer The demuxer whose subtitle stream will be changed.
636 \param new_num The number of the new subtitle track. The number must be
637 between 0 and ogg_d->n_text - 1.
639 \returns The Ogg stream number ( = page serial number) of the newly selected
642 int demux_ogg_sub_id(demuxer_t
*demuxer
, int index
) {
643 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
644 return (index
< 0) ? index
: (index
>= ogg_d
->n_text
) ? -1 : ogg_d
->text_ids
[index
];
647 /** \brief Translate the ogg track number into the subtitle number.
648 * \param demuxer The demuxer about whose subtitles we are inquiring.
649 * \param id The ogg track number of the subtitle track.
651 static int demux_ogg_sub_reverse_id(demuxer_t
*demuxer
, int id
) {
652 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
654 for (i
= 0; i
< ogg_d
->n_text
; i
++)
655 if (ogg_d
->text_ids
[i
] == id
) return i
;
659 static void demux_close_ogg(demuxer_t
* demuxer
);
661 static void fixup_vorbis_wf(sh_audio_t
*sh
, ogg_demuxer_t
*od
)
664 int ris
, init_error
= 0;
666 unsigned char *buf
[3];
669 ogg_stream_t
*os
= &od
->subs
[sh
->ds
->id
];
672 vorbis_info_init(&os
->vi
);
673 vorbis_comment_init(&vc
);
674 for(i
= 0; i
< 3; i
++) {
675 op
[i
].bytes
= ds_get_packet(sh
->ds
, &(op
[i
].packet
));
676 mp_msg(MSGT_DEMUX
,MSGL_V
, "fixup_vorbis_wf: i=%d, size=%ld\n", i
, op
[i
].bytes
);
677 if(op
[i
].bytes
< 0) {
678 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i
);
681 buf
[i
] = malloc(op
[i
].bytes
);
684 memcpy(buf
[i
], op
[i
].packet
, op
[i
].bytes
);
686 op
[i
].b_o_s
= (i
==0);
687 ris
= vorbis_synthesis_headerin(&os
->vi
,&vc
,&op
[i
]);
690 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i
, op
[i
].bytes
, ris
);
693 vorbis_comment_clear(&vc
);
695 os
->vi_initialized
= 1;
697 len
= op
[0].bytes
+ op
[1].bytes
+ op
[2].bytes
;
698 sh
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + len
+ len
/255 + 64);
699 ptr
= (unsigned char*) (sh
->wf
+1);
703 offset
+= store_ughvlc(&ptr
[offset
], op
[0].bytes
);
704 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, offset after 1st len = %u\n", offset
);
705 offset
+= store_ughvlc(&ptr
[offset
], op
[1].bytes
);
706 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, offset after 2nd len = %u\n", offset
);
707 for(i
= 0; i
< 3; i
++) {
708 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i
, op
[i
].bytes
, offset
);
709 memcpy(&ptr
[offset
], buf
[i
], op
[i
].bytes
);
710 offset
+= op
[i
].bytes
;
712 sh
->wf
->cbSize
= offset
;
713 mp_msg(MSGT_DEMUX
,MSGL_V
, "demux_ogg, extradata size: %d\n", sh
->wf
->cbSize
);
714 sh
->wf
= realloc(sh
->wf
, sizeof(WAVEFORMATEX
) + sh
->wf
->cbSize
);
716 if(op
[0].bytes
>= 29) {
718 int nombr
, minbr
, maxbr
;
720 sh
->channels
= ptr
[11];
721 sh
->samplerate
= sh
->wf
->nSamplesPerSec
= AV_RL32(&ptr
[12]);
722 maxbr
= AV_RL32(&ptr
[16]); //max
723 nombr
= AV_RL32(&ptr
[20]); //nominal
724 minbr
= AV_RL32(&ptr
[24]); //minimum
738 sh
->wf
->nAvgBytesPerSec
= br
;
739 sh
->wf
->wBitsPerSample
= 16;
740 sh
->samplesize
= (sh
->wf
->wBitsPerSample
+7)/8;
742 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
743 sh
->channels
, sh
->samplerate
, sh
->wf
->nAvgBytesPerSec
, maxbr
, nombr
, minbr
);
751 /// Open an ogg physical stream
752 // Not static because it's used also in demuxer_avi.c
753 int demux_ogg_open(demuxer_t
* demuxer
) {
754 ogg_demuxer_t
* ogg_d
;
757 int np
,s_no
, n_audio
= 0, n_video
= 0;
758 int audio_id
= -1, video_id
= -1, text_id
= -1;
759 ogg_sync_state
* sync
;
772 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
779 /// Try to get a page
780 ogg_d
->pos
+= ogg_d
->last_size
;
781 np
= ogg_sync_pageseek(sync
,page
);
784 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg demuxer : Bad page sync\n");
787 /// Need some more data
790 buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
791 len
= stream_read(s
,buf
,BLOCK_SIZE
);
792 if(len
== 0 && s
->eof
) {
795 ogg_sync_wrote(sync
,len
);
798 ogg_d
->last_size
= np
;
799 // We got one page now
801 if( ! ogg_page_bos(page
) ) { // It's not a beginning page
802 // Header parsing end here, we need to get the page otherwise it will be lost
803 int id
= demux_ogg_get_page_stream(ogg_d
,NULL
);
805 ogg_stream_pagein(&ogg_d
->subs
[id
].stream
,page
);
807 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page
));
811 /// Init the data structure needed for a logical stream
812 ogg_d
->subs
= realloc_struct(ogg_d
->subs
,ogg_d
->num_sub
+1,sizeof(ogg_stream_t
));
813 memset(&ogg_d
->subs
[ogg_d
->num_sub
],0,sizeof(ogg_stream_t
));
814 /// Get the stream serial number
815 s_no
= ogg_page_serialno(page
);
816 ogg_stream_init(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,s_no
);
817 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg : Found a stream with serial=%d\n",s_no
);
818 // Take the first page
819 ogg_stream_pagein(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,page
);
820 // Get first packet of the page
821 ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,&pack
);
827 ogg_d
->subs
[ogg_d
->num_sub
].ogg_d
= ogg_d
;
830 if(pack
.bytes
>= 7 && ! strncmp(&pack
.packet
[1],"vorbis", 6) ) {
831 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
832 sh_a
->format
= FOURCC_VORBIS
;
833 ogg_d
->subs
[ogg_d
->num_sub
].vorbis
= 1;
834 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
836 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
837 } else if (pack
.bytes
>= 80 && !strncmp(pack
.packet
,"Speex", 5)) {
838 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
839 sh_a
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + pack
.bytes
);
840 sh_a
->format
= FOURCC_SPEEX
;
841 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(&pack
.packet
[36]);
842 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL32(&pack
.packet
[48]);
843 sh_a
->wf
->wFormatTag
= sh_a
->format
;
844 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&pack
.packet
[52]);
845 sh_a
->wf
->nBlockAlign
= 0;
846 sh_a
->wf
->wBitsPerSample
= 16;
847 sh_a
->samplesize
= 2;
848 sh_a
->wf
->cbSize
= pack
.bytes
;
849 memcpy(&sh_a
->wf
[1], pack
.packet
, pack
.bytes
);
851 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
;
852 ogg_d
->subs
[ogg_d
->num_sub
].speex
= 1;
853 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
855 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
858 # ifdef CONFIG_OGGTHEORA
859 } else if (pack
.bytes
>= 7 && !strncmp (&pack
.packet
[1], "theora", 6)) {
864 theora_info_init (&inf
);
865 theora_comment_init (&cc
);
867 errorCode
= theora_decode_header (&inf
, &cc
, &pack
);
869 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Theora header parsing failed: %i \n",
873 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
875 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
876 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
877 sh_v
->bih
->biCompression
= sh_v
->format
= FOURCC_THEORA
;
878 sh_v
->fps
= ((double)inf
.fps_numerator
)/
879 (double)inf
.fps_denominator
;
880 sh_v
->frametime
= ((double)inf
.fps_denominator
)/
881 (double)inf
.fps_numerator
;
882 sh_v
->disp_w
= sh_v
->bih
->biWidth
= inf
.frame_width
;
883 sh_v
->disp_h
= sh_v
->bih
->biHeight
= inf
.frame_height
;
884 sh_v
->bih
->biBitCount
= 24;
885 sh_v
->bih
->biPlanes
= 3;
886 sh_v
->bih
->biSizeImage
= ((sh_v
->bih
->biBitCount
/8) *
887 sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
);
888 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
889 ogg_d
->subs
[ogg_d
->num_sub
].theora
= 1;
890 ogg_d
->subs
[ogg_d
->num_sub
].keyframe_frequency_force
= inf
.keyframe_frequency_force
;
891 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
893 mp_msg(MSGT_DEMUX
,MSGL_INFO
,
894 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
896 (int)inf
.version_major
,
897 (int)inf
.version_minor
,
898 (int)inf
.version_subminor
,
900 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
902 theora_comment_clear(&cc
);
903 theora_info_clear(&inf
);
904 # endif /* CONFIG_OGGTHEORA */
905 } else if (pack
.bytes
>= 4 && !strncmp (&pack
.packet
[0], "fLaC", 4)) {
906 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
907 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
908 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
910 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 1;
912 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
913 } else if (pack
.bytes
>= 51 && !strncmp(&pack
.packet
[1], "FLAC", 4)) {
914 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
915 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
916 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
918 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 2;
919 sh_a
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + 34);
920 sh_a
->wf
->wFormatTag
= sh_a
->format
;
921 sh_a
->wf
->cbSize
= 34;
922 memcpy(&sh_a
->wf
[1], &pack
.packet
[17], 34);
923 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
925 /// Check for old header
926 } else if(pack
.bytes
>= 142 && ! strncmp(&pack
.packet
[1],"Direct Show Samples embedded in Ogg",35) ) {
929 if(AV_RL32(pack
.packet
+96) == 0x05589f80 && pack
.bytes
>= 184) {
930 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
931 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
932 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
933 sh_v
->bih
->biCompression
=
934 sh_v
->format
= mmioFOURCC(pack
.packet
[68],pack
.packet
[69],
935 pack
.packet
[70],pack
.packet
[71]);
936 sh_v
->frametime
= AV_RL64(pack
.packet
+164)*0.0000001;
937 sh_v
->fps
= 1/sh_v
->frametime
;
938 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(pack
.packet
+176);
939 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(pack
.packet
+180);
940 sh_v
->bih
->biBitCount
= AV_RL16(pack
.packet
+182);
941 if(!sh_v
->bih
->biBitCount
) sh_v
->bih
->biBitCount
=24; // hack, FIXME
942 sh_v
->bih
->biPlanes
=1;
943 sh_v
->bih
->biSizeImage
=(sh_v
->bih
->biBitCount
>>3)*sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
;
945 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
946 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
948 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
949 ogg_d
->num_sub
,pack
.packet
[68],pack
.packet
[69],pack
.packet
[70],pack
.packet
[71],n_video
-1);
950 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
952 } else if(AV_RL32(pack
.packet
+96) == 0x05589F81) {
953 unsigned int extra_size
;
954 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
955 extra_size
= AV_RL16(pack
.packet
+140);
956 sh_a
->wf
= calloc(1,sizeof(WAVEFORMATEX
)+extra_size
);
957 sh_a
->format
= sh_a
->wf
->wFormatTag
= AV_RL16(pack
.packet
+124);
958 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(pack
.packet
+126);
959 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(pack
.packet
+128);
960 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(pack
.packet
+132);
961 sh_a
->wf
->nBlockAlign
= AV_RL16(pack
.packet
+136);
962 sh_a
->wf
->wBitsPerSample
= AV_RL16(pack
.packet
+138);
963 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+7)/8;
964 sh_a
->wf
->cbSize
= extra_size
;
966 memcpy(((char *)sh_a
->wf
)+sizeof(WAVEFORMATEX
),pack
.packet
+142,extra_size
);
968 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
969 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
971 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d
->num_sub
,sh_a
->format
,n_audio
-1);
972 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_wave_header(sh_a
->wf
,MSGL_V
);
974 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d
->num_sub
);
977 } else if ( (*pack
.packet
& PACKET_TYPE_BITS
) == PACKET_TYPE_HEADER
&&
978 pack
.bytes
>= (int)sizeof(stream_header
)+1) {
979 stream_header
*st
= (stream_header
*)(pack
.packet
+1);
981 if(strncmp(st
->streamtype
,"video",5) == 0) {
982 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
983 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
984 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
985 sh_v
->bih
->biCompression
=
986 sh_v
->format
= mmioFOURCC(st
->subtype
[0],st
->subtype
[1],
987 st
->subtype
[2],st
->subtype
[3]);
988 sh_v
->frametime
= AV_RL64(&st
->time_unit
)*0.0000001;
989 sh_v
->fps
= 1.0/sh_v
->frametime
;
990 sh_v
->bih
->biBitCount
= AV_RL16(&st
->bits_per_sample
);
991 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(&st
->sh
.video
.width
);
992 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(&st
->sh
.video
.height
);
993 if(!sh_v
->bih
->biBitCount
) sh_v
->bih
->biBitCount
=24; // hack, FIXME
994 sh_v
->bih
->biPlanes
=1;
995 sh_v
->bih
->biSizeImage
=(sh_v
->bih
->biBitCount
>>3)*sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
;
997 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
998 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
1000 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1001 ogg_d
->num_sub
,st
->subtype
[0],st
->subtype
[1],st
->subtype
[2],st
->subtype
[3],n_video
-1);
1002 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
1003 /// New audio header
1004 } else if(strncmp(st
->streamtype
,"audio",5) == 0) {
1006 unsigned int extra_size
= AV_RL32(&st
->size
) - sizeof(stream_header
);
1007 unsigned int extra_offset
= 0;
1009 memcpy(buffer
,st
->subtype
,4);
1012 /* Nasty workaround. stream_header.size seems not to contain the real
1013 size in all cases. There are four extra bytes that are unaccounted
1014 for in front of the real codec initialization data _at least_ for
1015 AAC. So far I've only seen those bytes being all 0, so we can
1016 just skip them here. */
1017 if ((strtol(buffer
, NULL
, 16) == 0xff) && (extra_size
>= 4)) {
1022 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
1023 sh_a
->wf
= calloc(1,sizeof(WAVEFORMATEX
)+extra_size
);
1024 sh_a
->format
= sh_a
->wf
->wFormatTag
= strtol(buffer
, NULL
, 16);
1025 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(&st
->sh
.audio
.channels
);
1026 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL64(&st
->samples_per_unit
);
1027 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&st
->sh
.audio
.avgbytespersec
);
1028 sh_a
->wf
->nBlockAlign
= AV_RL16(&st
->sh
.audio
.blockalign
);
1029 sh_a
->wf
->wBitsPerSample
= AV_RL16(&st
->bits_per_sample
);
1030 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+7)/8;
1031 sh_a
->wf
->cbSize
= extra_size
;
1033 memcpy(((char *)sh_a
->wf
)+sizeof(WAVEFORMATEX
),((char *)(st
+1))+extra_offset
,extra_size
);
1035 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
1036 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
1038 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d
->num_sub
,sh_a
->format
,n_audio
-1);
1039 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_wave_header(sh_a
->wf
,MSGL_V
);
1041 /// Check for text (subtitles) header
1042 } else if (strncmp(st
->streamtype
, "text", 4) == 0) {
1043 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n", ogg_d
->num_sub
, ogg_d
->n_text
);
1044 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= AV_RL64(&st
->time_unit
)/10;
1045 ogg_d
->subs
[ogg_d
->num_sub
].text
= 1;
1046 ogg_d
->subs
[ogg_d
->num_sub
].id
= ogg_d
->n_text
;
1047 if (demuxer
->sub
->id
== ogg_d
->n_text
)
1048 text_id
= ogg_d
->num_sub
;
1049 new_sh_sub(demuxer
, ogg_d
->n_text
);
1051 ogg_d
->text_ids
= realloc_struct(ogg_d
->text_ids
, ogg_d
->n_text
, sizeof(int));
1052 ogg_d
->text_ids
[ogg_d
->n_text
- 1] = ogg_d
->num_sub
;
1053 ogg_d
->text_langs
= realloc_struct(ogg_d
->text_langs
, ogg_d
->n_text
, sizeof(char *));
1054 ogg_d
->text_langs
[ogg_d
->n_text
- 1] = NULL
;
1055 //// Unknown header type
1057 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d
->num_sub
);
1058 /// Unknown (invalid ?) header
1060 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg stream %d is of an unknown type\n",ogg_d
->num_sub
);
1063 demux_stream_t
* ds
= NULL
;
1065 // If the audio stream is not defined we took the first one
1066 if(demuxer
->audio
->id
== -1) {
1067 demuxer
->audio
->id
= n_audio
- 1;
1068 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1070 /// Is it the stream we want
1071 if(demuxer
->audio
->id
== n_audio
- 1) {
1072 demuxer
->audio
->sh
= sh_a
;
1073 sh_a
->ds
= demuxer
->audio
;
1074 ds
= demuxer
->audio
;
1075 audio_id
= ogg_d
->num_sub
;
1080 if(demuxer
->video
->id
== -1) {
1081 demuxer
->video
->id
= n_video
- 1;
1082 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1084 if(demuxer
->video
->id
== n_video
- 1) {
1085 demuxer
->video
->sh
= sh_v
;
1086 sh_v
->ds
= demuxer
->video
;
1087 ds
= demuxer
->video
;
1088 video_id
= ogg_d
->num_sub
;
1091 /// Add the header packets if the stream isn't seekable
1092 if(ds
&& !s
->end_pos
) {
1093 /// Finish the page, otherwise packets will be lost
1095 demux_ogg_add_packet(ds
,&ogg_d
->subs
[ogg_d
->num_sub
],ogg_d
->num_sub
,&pack
);
1096 } while(ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,&pack
) == 1);
1102 if(!n_video
&& !n_audio
) {
1106 if(!n_video
|| video_id
< 0)
1107 demuxer
->video
->id
= -2;
1109 demuxer
->video
->id
= video_id
;
1110 if(!n_audio
|| audio_id
< 0)
1111 demuxer
->audio
->id
= -2;
1113 demuxer
->audio
->id
= audio_id
;
1114 /* Disable the subs only if there are no text streams at all.
1115 Otherwise the stream to display might be chosen later when the comment
1116 packet is encountered and the user used -slang instead of -sid. */
1118 demuxer
->sub
->id
= -2;
1119 else if (text_id
>= 0) {
1120 demuxer
->sub
->id
= text_id
;
1121 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id
);
1124 ogg_d
->final_granulepos
=0;
1126 demuxer
->seekable
= 0;
1128 demuxer
->movi_start
= s
->start_pos
; // Needed for XCD (Ogg written in MODE2)
1129 demuxer
->movi_end
= s
->end_pos
;
1130 demuxer
->seekable
= 1;
1131 demux_ogg_scan_stream(demuxer
);
1134 mp_msg(MSGT_DEMUX
,MSGL_V
,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio
,n_audio
>1?"s":"",n_video
,n_video
>1?"s":"",ogg_d
->n_text
,ogg_d
->n_text
>1?"s":"");
1136 sh_a
= demuxer
->audio
->sh
;
1138 if(sh_a
->format
== FOURCC_VORBIS
)
1139 fixup_vorbis_wf(sh_a
, ogg_d
);
1141 return DEMUXER_TYPE_OGG
;
1148 static int demux_ogg_fill_buffer(demuxer_t
*d
, demux_stream_t
*dsds
) {
1149 ogg_demuxer_t
* ogg_d
;
1152 ogg_sync_state
* sync
;
1153 ogg_stream_state
* os
;
1160 sync
= &ogg_d
->sync
;
1161 page
= &ogg_d
->page
;
1163 /// Find the stream we are working on
1164 if ( (id
= demux_ogg_get_page_stream(ogg_d
,&os
)) < 0) {
1165 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer : can't get current stream\n");
1172 /// Try to get some packet from the current page
1173 while( (np
= ogg_stream_packetout(os
,&pack
)) != 1) {
1174 /// No packet we go the next page
1179 ogg_d
->pos
+= ogg_d
->last_size
;
1180 /// Get the next page from the physical stream
1181 while( (pa
= ogg_sync_pageseek(sync
,page
)) <= 0) {
1182 /// Error : we skip some bytes
1184 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg : Page out not synced, we skip some bytes\n");
1188 /// We need more data
1189 buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
1190 len
= stream_read(s
,buf
,BLOCK_SIZE
);
1191 if(len
== 0 && s
->eof
) {
1192 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg : Stream EOF !!!!\n");
1195 ogg_sync_wrote(sync
,len
);
1197 ogg_d
->last_size
= pa
;
1198 /// Find the page's logical stream
1199 if( (id
= demux_ogg_get_page_stream(ogg_d
,&os
)) < 0) {
1200 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer error : we met an unknown stream\n");
1204 if(ogg_stream_pagein(os
,page
) == 0)
1206 /// Page was invalid => retry
1207 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg demuxer : got invalid page !!!!!\n");
1208 ogg_d
->pos
+= ogg_d
->last_size
;
1210 } else /// Packet was corrupted
1211 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg : bad packet in stream %d\n",id
);
1214 /// Is the actual logical stream in use ?
1215 if(id
== d
->audio
->id
)
1217 else if(id
== d
->video
->id
)
1219 else if (ogg_d
->subs
[id
].text
)
1223 if(!demux_ogg_add_packet(ds
,&ogg_d
->subs
[id
],id
,&pack
))
1224 continue; /// Unuseful packet, get another
1225 d
->filepos
= ogg_d
->pos
;
1233 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1234 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1235 demuxer_t
* init_avi_with_ogg(demuxer_t
* demuxer
) {
1237 ogg_demuxer_t
*ogg_d
;
1239 uint32_t hdrsizes
[3];
1241 sh_audio_t
*sh_audio
= demuxer
->audio
->sh
;
1243 uint8_t *extradata
= sh_audio
->wf
+ 1;
1245 unsigned char *p
= NULL
,*buf
;
1248 /// Check that the cbSize is big enough for the following reads
1249 if(sh_audio
->wf
->cbSize
< 22+3*4) {
1250 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Initial audio header is too small !!!!!\n");
1253 /// Get the size of the 3 header packet
1255 for (i
= 0; i
< 3; i
++) {
1256 hdrsizes
[i
] = AV_RL32(extradata
);
1259 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1262 if(sh_audio
->wf
->cbSize
< 22+3*4+hdrsizes
[0]+hdrsizes
[1] + hdrsizes
[2]) {
1263 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Audio header is too small !!!!!\n");
1267 // Build the ogg demuxer private datas
1268 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
1270 ogg_d
->subs
= malloc(sizeof(ogg_stream_t
));
1271 ogg_d
->subs
[0].vorbis
= 1;
1273 // Init the ogg physical stream
1274 ogg_sync_init(&ogg_d
->sync
);
1276 // Get the first page of the stream : we assume there only 1 logical stream
1277 while((np
= ogg_sync_pageout(&ogg_d
->sync
,&ogg_d
->page
)) <= 0 ) {
1279 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg error : Can't init using first stream packets\n");
1284 plen
= ds_get_packet(demuxer
->audio
,&p
);
1285 buf
= ogg_sync_buffer(&ogg_d
->sync
,plen
);
1287 ogg_sync_wrote(&ogg_d
->sync
,plen
);
1289 // Init the logical stream
1290 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d
->page
));
1291 ogg_stream_init(&ogg_d
->subs
[0].stream
,ogg_page_serialno(&ogg_d
->page
));
1293 ogg_stream_pagein(&ogg_d
->subs
[0].stream
,&ogg_d
->page
);
1295 // Create the ds_stream and the ogg demuxer
1296 s
= new_ds_stream(demuxer
->audio
);
1297 od
= new_demuxer(s
,DEMUXER_TYPE_OGG
,0,-2,-2,NULL
);
1299 /// Add the header packets in the ogg demuxer audio stream
1300 for (i
= 0; i
< 3; i
++) {
1301 dp
= new_demux_packet(hdrsizes
[i
]);
1302 memcpy(dp
->buffer
,extradata
,hdrsizes
[i
]);
1303 ds_add_packet(od
->audio
,dp
);
1304 extradata
+= hdrsizes
[i
];
1307 // Finish setting up the ogg demuxer
1309 sh_audio
= new_sh_audio(od
,0);
1312 od
->audio
->sh
= sh_audio
;
1313 sh_audio
->ds
= od
->audio
;
1314 sh_audio
->format
= FOURCC_VORBIS
;
1315 fixup_vorbis_wf(sh_audio
, ogg_d
);
1317 /// Return the joined demuxers
1318 return new_demuxers_demuxer(demuxer
,od
,demuxer
);
1321 demuxer
->audio
->id
= -2;
1326 static void demux_ogg_seek(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
) {
1327 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1328 ogg_sync_state
* sync
= &ogg_d
->sync
;
1329 ogg_page
* page
= &ogg_d
->page
;
1330 ogg_stream_state
* oss
;
1335 int i
,sp
,first
,precision
=1,do_seek
=1;
1336 vorbis_info
* vi
= NULL
;
1337 int64_t gp
= 0, old_gp
;
1344 ogg_int64_t granulepos_orig
;
1346 if(demuxer
->video
->id
>= 0) {
1347 ds
= demuxer
->video
;
1348 rate
= ogg_d
->subs
[ds
->id
].samplerate
;
1350 ds
= demuxer
->audio
;
1351 os
= &ogg_d
->subs
[ds
->id
];
1353 rate
= (float)vi
->rate
;
1354 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
1357 os
= &ogg_d
->subs
[ds
->id
];
1360 old_gp
= os
->lastpos
;
1361 old_pos
= ogg_d
->pos
;
1363 //calculate the granulepos to seek to
1364 gp
= flags
& SEEK_ABSOLUTE
? 0 : os
->lastpos
;
1365 if(flags
& SEEK_FACTOR
) {
1366 if (ogg_d
->final_granulepos
> 0)
1367 gp
+= ogg_d
->final_granulepos
* rel_seek_secs
;
1369 gp
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) * os
->lastpos
/ ogg_d
->pos
;
1371 gp
+= rel_seek_secs
* rate
;
1374 //calculate the filepos to seek to
1375 if(ogg_d
->syncpoints
) {
1376 for(sp
= 0; sp
< ogg_d
->num_syncpoint
; sp
++) {
1377 if(ogg_d
->syncpoints
[sp
].granulepos
>= gp
) break;
1380 if(sp
>= ogg_d
->num_syncpoint
) return;
1381 if (sp
> 0 && ogg_d
->syncpoints
[sp
].granulepos
- gp
> gp
- ogg_d
->syncpoints
[sp
-1].granulepos
)
1383 if (ogg_d
->syncpoints
[sp
].granulepos
== os
->lastpos
) {
1384 if (sp
> 0 && gp
< os
->lastpos
) sp
--;
1385 if (sp
< ogg_d
->num_syncpoint
-1 && gp
> os
->lastpos
) sp
++;
1387 pos
= ogg_d
->syncpoints
[sp
].page_pos
;
1390 pos
= flags
& SEEK_ABSOLUTE
? 0 : ogg_d
->pos
;
1391 if(flags
& SEEK_FACTOR
)
1392 pos
+= (demuxer
->movi_end
- demuxer
->movi_start
) * rel_seek_secs
;
1394 if (ogg_d
->final_granulepos
> 0) {
1395 pos
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) / (ogg_d
->final_granulepos
/ rate
);
1396 } else if (os
->lastpos
> 0) {
1397 pos
+= rel_seek_secs
* ogg_d
->pos
/ (os
->lastpos
/ rate
);
1400 if (pos
< 0) pos
= 0;
1401 if (pos
> (demuxer
->movi_end
- demuxer
->movi_start
))
1402 pos
= demuxer
->movi_end
- demuxer
->movi_start
;
1403 } // if(ogg_d->syncpoints)
1407 stream_seek(demuxer
->stream
,pos
+demuxer
->movi_start
);
1408 ogg_sync_reset(sync
);
1409 for(i
= 0 ; i
< ogg_d
->num_sub
; i
++) {
1410 ogg_stream_reset(&ogg_d
->subs
[i
].stream
);
1411 ogg_d
->subs
[i
].lastpos
= ogg_d
->subs
[i
].lastsize
= 0;
1414 ogg_d
->last_size
= 0;
1415 /* we just guess that we reached correct granulepos, in case a
1416 subsequent search occurs before we read a valid granulepos */
1418 first
= !(ogg_d
->syncpoints
);
1421 ogg_d
->pos
+= ogg_d
->last_size
;
1422 ogg_d
->last_size
= 0;
1423 np
= ogg_sync_pageseek(sync
,page
);
1427 if(np
<= 0) { // We need more data
1428 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
1429 int len
= stream_read(demuxer
->stream
,buf
,BLOCK_SIZE
);
1430 if(len
== 0 && demuxer
->stream
->eof
) {
1431 mp_msg(MSGT_DEMUX
,MSGL_V
,"EOF while trying to seek !!!!\n");
1434 ogg_sync_wrote(sync
,len
);
1437 ogg_d
->last_size
= np
;
1438 if(ogg_page_serialno(page
) != oss
->serialno
)
1441 if(ogg_stream_pagein(oss
,page
) != 0)
1445 np
= ogg_stream_packetout(oss
,&op
);
1450 if (first
) { /* Discard the first packet as it's probably broken,
1451 and we don't have any other means to decide whether it is
1456 is_gp_valid
= (op
.granulepos
>= 0);
1457 granulepos_orig
=op
.granulepos
;
1458 demux_ogg_read_packet(os
,&op
,&pts
,&is_keyframe
,samplesize
);
1459 if (precision
&& is_gp_valid
) {
1461 if (abs(gp
- op
.granulepos
) > rate
&& (op
.granulepos
!= old_gp
)) {
1462 //prepare another seek because we are off by more than 1s
1463 pos
+= (gp
- op
.granulepos
) * (pos
- old_pos
) / (op
.granulepos
- old_gp
);
1464 if (pos
< 0) pos
= 0;
1465 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1471 if (is_gp_valid
&& pos
> 0 && old_gp
> gp
1472 && 2 * (old_gp
- op
.granulepos
) < old_gp
- gp
) {
1473 /* prepare another seek because looking for a syncpoint
1474 destroyed the backward search */
1475 pos
= old_pos
- 1.5 * (old_pos
- pos
);
1476 if (pos
< 0) pos
= 0;
1477 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1482 if(!precision
&& (is_keyframe
|| os
->vorbis
|| os
->speex
) ) {
1483 if (sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
)) {
1485 vo_osd_changed(OSDTYPE_SUBTITLE
);
1487 op
.granulepos
=granulepos_orig
;
1488 demux_ogg_add_packet(ds
,os
,ds
->id
,&op
);
1494 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Can't find the good packet :(\n");
1498 static void demux_close_ogg(demuxer_t
* demuxer
) {
1499 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1500 ogg_stream_t
* os
= NULL
;
1510 ogg_sync_clear(&ogg_d
->sync
);
1513 for (i
= 0; i
< ogg_d
->num_sub
; i
++)
1515 os
= &ogg_d
->subs
[i
];
1516 ogg_stream_clear(&os
->stream
);
1517 if(os
->vi_initialized
)
1518 vorbis_info_clear(&os
->vi
);
1522 if(ogg_d
->syncpoints
)
1523 free(ogg_d
->syncpoints
);
1524 if (ogg_d
->text_ids
)
1525 free(ogg_d
->text_ids
);
1526 if (ogg_d
->text_langs
) {
1527 for (i
= 0; i
< ogg_d
->n_text
; i
++)
1528 if (ogg_d
->text_langs
[i
]) free(ogg_d
->text_langs
[i
]);
1529 free(ogg_d
->text_langs
);
1534 static int demux_ogg_control(demuxer_t
*demuxer
,int cmd
, void *arg
){
1535 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1539 if(demuxer
->video
->id
>= 0) {
1540 os
= &ogg_d
->subs
[demuxer
->video
->id
];
1541 rate
= os
->samplerate
;
1543 os
= &ogg_d
->subs
[demuxer
->audio
->id
];
1549 case DEMUXER_CTRL_GET_TIME_LENGTH
:
1550 if (ogg_d
->final_granulepos
<=0) return DEMUXER_CTRL_DONTKNOW
;
1551 *(double *)arg
=(double)ogg_d
->final_granulepos
/ rate
;
1552 return DEMUXER_CTRL_GUESS
;
1554 case DEMUXER_CTRL_GET_PERCENT_POS
:
1555 if (ogg_d
->final_granulepos
<=0) return DEMUXER_CTRL_DONTKNOW
;
1556 *(int *)arg
=(os
->lastpos
*100) / ogg_d
->final_granulepos
;
1557 return DEMUXER_CTRL_OK
;
1560 return DEMUXER_CTRL_NOTIMPL
;
1566 const demuxer_desc_t demuxer_desc_ogg
= {
1573 1, // safe autodetect
1575 demux_ogg_fill_buffer
,