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.
31 #include "stream/stream.h"
34 #include "ffmpeg_files/intreadwrite.h"
36 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
37 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
38 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
41 #include <tremor/ogg.h>
42 #include <tremor/ivorbiscodec.h>
45 #include <vorbis/codec.h>
48 #ifdef CONFIG_OGGTHEORA
49 #include <theora/theora.h>
50 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
53 #define BLOCK_SIZE 4096
55 /* Theora decoder context : we won't be able to interpret granule positions
56 * without using theora_granule_time with the theora_state of the stream.
57 * This is duplicated in `vd_theora.c'; put this in a common header?
59 #ifdef CONFIG_OGGTHEORA
60 typedef struct theora_struct_st
{
68 // Header for the new header format
69 typedef struct stream_header_video
73 } stream_header_video
;
75 typedef struct stream_header_audio
78 ogg_int16_t blockalign
;
79 ogg_int32_t avgbytespersec
;
80 } stream_header_audio
;
82 typedef struct __attribute__((__packed__
)) stream_header
87 ogg_int32_t size
; // size of the structure
89 ogg_int64_t time_unit
; // in reference time
90 ogg_int64_t samples_per_unit
;
91 ogg_int32_t default_len
; // in media time
93 ogg_int32_t buffersize
;
94 ogg_int16_t bits_per_sample
;
101 stream_header_video video
;
103 stream_header_audio audio
;
107 /// Our private datas
109 typedef struct ogg_syncpoint
{
115 typedef struct ogg_stream
{
116 /// Timestamping stuff
117 float samplerate
; /// granulpos 2 time
120 int keyframe_frequency_force
;
122 // Logical stream state
123 ogg_stream_state stream
;
138 typedef struct ogg_demuxer
{
139 /// Physical stream state
146 ogg_syncpoint_t
* syncpoints
;
148 off_t pos
, last_size
;
149 int64_t initial_granulepos
;
150 int64_t final_granulepos
;
153 /* Used for subtitle switching. */
159 #define NUM_VORBIS_HDR_PACKETS 3
161 /// Some defines from OggDS
162 #define PACKET_TYPE_HEADER 0x01
163 #define PACKET_TYPE_BITS 0x07
164 #define PACKET_LEN_BITS01 0xc0
165 #define PACKET_LEN_BITS2 0x02
166 #define PACKET_IS_SYNCPOINT 0x08
168 extern char *dvdsub_lang
, *audio_lang
;
170 //-------- subtitle support - should be moved to decoder layer, and queue
171 // - subtitles up in demuxer buffer...
173 #include "subreader.h"
174 #include "libvo/sub.h"
175 #define OGG_SUB_MAX_LINE 128
177 static subtitle ogg_sub
;
180 static void demux_ogg_add_sub (ogg_stream_t
* os
,ogg_packet
* pack
) {
182 char *packet
= pack
->packet
;
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],
192 if (((unsigned char)packet
[0]) == 0x88) { // some subtitle text
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;
199 if (pack
->bytes
< lcv
)
201 for (i
= hdrlen
; i
> 0; i
--) {
203 duration
|= (unsigned char)packet
[i
];
205 if (hdrlen
> 0 && duration
> 0) {
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]);
219 subcp_recode(&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
) {
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
)
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
);
253 *os
= &ogg_d
->subs
[id
].stream
;
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
;
266 if(*pack
->packet
& PACKET_TYPE_HEADER
)
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
;
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
;
281 pack
->granulepos
+= os
->lastsize
;
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! */
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
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;
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)
323 if(*pack
->packet
& PACKET_TYPE_HEADER
)
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
)
336 *pts
= pack
->granulepos
/os
->samplerate
;
337 // Save the packet length and timestamp
341 os
->lastsize
|= pack
->packet
[hdrlen
];
344 os
->lastpos
= pack
->granulepos
;
350 // check if clang has substring from comma separated langlist
351 static int demux_ogg_check_lang(const char *clang
, const char *langlist
)
355 if (!langlist
|| !*langlist
)
357 while ((c
= strchr(langlist
, ',')))
359 if (!strncasecmp(clang
, langlist
, c
- langlist
))
363 if (!strncasecmp(clang
, langlist
, strlen(langlist
)))
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
;
376 ogg_demuxer_t
*ogg_d
= d
->priv
;
377 static const struct 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" },
396 if (!strncasecmp(*cmt
, "LANGUAGE=", 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
);
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
))
420 d
->opts
->sub_id
= index
;
421 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id
, val
);
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
)] == '=')
433 val
= *cmt
+ strlen(table
[i
].ogg
) + 1;
438 demux_info_add(d
, hdr
, val
);
439 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, " %s: %s\n", hdr
, val
);
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
;
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))
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
);
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
);
474 // discard first two packets, they contain the header and comment
475 if (os
->hdr_packets
< 2) {
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
)))
489 // For vorbis packet the packet is the data, for other codec we must jump
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
);
498 /// Clear subtitles if necessary (for broken files)
499 if (sub_clear_text(&ogg_sub
, pts
)) {
501 vo_osd_changed(OSDTYPE_SUBTITLE
);
504 dp
= new_demux_packet(pack
->bytes
-(data
-pack
->packet
));
505 memcpy(dp
->buffer
,data
,pack
->bytes
-(data
-pack
->packet
));
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
);
514 /// if -forceidx build a table of all syncpoints to make seeking easier
515 /// otherwise try to get at least the final_granulepos
516 static void demux_ogg_scan_stream(demuxer_t
* demuxer
) {
517 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
518 stream_t
*s
= demuxer
->stream
;
519 ogg_sync_state
* sync
= &ogg_d
->sync
;
520 ogg_page
* page
= &ogg_d
->page
;
521 ogg_stream_state
* oss
;
524 int np
,sid
,p
,samplesize
=1;
526 pos
= last_pos
= demuxer
->movi_start
;
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
;
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) {
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
);
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
++;
598 if(p
> 1 || (p
== 1 && ! ogg_page_continued(page
)))
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
);
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
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");
628 ogg_sync_wrote(sync
,len
);
631 demux_ogg_get_page_stream(ogg_d
,&oss
);
632 ogg_stream_pagein(oss
,page
);
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
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
;
665 for (i
= 0; i
< ogg_d
->n_text
; i
++)
666 if (ogg_d
->text_ids
[i
] == id
) return i
;
670 static void demux_close_ogg(demuxer_t
* demuxer
);
672 static void fixup_vorbis_wf(sh_audio_t
*sh
, ogg_demuxer_t
*od
)
675 int ris
, init_error
= 0;
677 unsigned char *buf
[3];
680 ogg_stream_t
*os
= &od
->subs
[sh
->ds
->id
];
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
);
692 buf
[i
] = malloc(op
[i
].bytes
);
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
]);
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
);
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);
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) {
729 int nombr
, minbr
, maxbr
;
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
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
);
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
;
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
;
783 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
790 /// Try to get a page
791 ogg_d
->pos
+= ogg_d
->last_size
;
792 np
= ogg_sync_pageseek(sync
,page
);
795 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg demuxer : Bad page sync\n");
798 /// Need some more data
801 buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
802 len
= stream_read(s
,buf
,BLOCK_SIZE
);
803 if(len
== 0 && s
->eof
) {
806 ogg_sync_wrote(sync
,len
);
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
);
816 ogg_stream_pagein(&ogg_d
->subs
[id
].stream
,page
);
818 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page
));
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
);
838 ogg_d
->subs
[ogg_d
->num_sub
].ogg_d
= ogg_d
;
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
;
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
;
866 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
869 # ifdef CONFIG_OGGTHEORA
870 } else if (pack
.bytes
>= 7 && !strncmp (&pack
.packet
[1], "theora", 6)) {
875 theora_info_init (&inf
);
876 theora_comment_init (&cc
);
878 errorCode
= theora_decode_header (&inf
, &cc
, &pack
);
880 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Theora header parsing failed: %i \n",
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
;
904 mp_msg(MSGT_DEMUX
,MSGL_INFO
,
905 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
907 (int)inf
.version_major
,
908 (int)inf
.version_minor
,
909 (int)inf
.version_subminor
,
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
;
921 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 1;
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
;
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) ) {
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
;
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
);
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
;
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
;
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
);
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
);
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);
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
;
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) {
1017 unsigned int extra_size
= AV_RL32(&st
->size
) - sizeof(stream_header
);
1018 unsigned int extra_offset
= 0;
1020 memcpy(buffer
,st
->subtype
,4);
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)) {
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
;
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
;
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
);
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
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
1071 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg stream %d is of an unknown type\n",ogg_d
->num_sub
);
1074 demux_stream_t
* ds
= NULL
;
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
;
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
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);
1113 if(!n_video
&& !n_audio
) {
1117 if(!n_video
|| video_id
< 0)
1118 demuxer
->video
->id
= -2;
1120 demuxer
->video
->id
= video_id
;
1121 if(!n_audio
|| audio_id
< 0)
1122 demuxer
->audio
->id
= -2;
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. */
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
;
1138 demuxer
->seekable
= 0;
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
;
1153 if(sh_a
->format
== FOURCC_VORBIS
)
1154 fixup_vorbis_wf(sh_a
, ogg_d
);
1156 return DEMUXER_TYPE_OGG
;
1163 static int demux_ogg_fill_buffer(demuxer_t
*d
, demux_stream_t
*dsds
) {
1164 ogg_demuxer_t
* ogg_d
;
1167 ogg_sync_state
* sync
;
1168 ogg_stream_state
* os
;
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");
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
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
1199 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg : Page out not synced, we skip some bytes\n");
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");
1210 ogg_sync_wrote(sync
,len
);
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");
1219 if(ogg_stream_pagein(os
,page
) == 0)
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
);
1229 /// Is the actual logical stream in use ?
1230 if(id
== d
->audio
->id
)
1232 else if(id
== d
->video
->id
)
1234 else if (ogg_d
->subs
[id
].text
)
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
;
1248 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1249 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1250 demuxer_t
* init_avi_with_ogg(demuxer_t
* demuxer
) {
1251 struct MPOpts
*opts
= demuxer
->opts
;
1253 ogg_demuxer_t
*ogg_d
;
1255 uint32_t hdrsizes
[3];
1257 sh_audio_t
*sh_audio
= demuxer
->audio
->sh
;
1259 uint8_t *extradata
= sh_audio
->wf
+ 1;
1261 unsigned char *p
= NULL
,*buf
;
1264 /// Check that the cbSize is big enough for the following reads
1265 if(sh_audio
->wf
->cbSize
< 22+3*4) {
1266 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Initial audio header is too small !!!!!\n");
1269 /// Get the size of the 3 header packet
1271 for (i
= 0; i
< 3; i
++) {
1272 hdrsizes
[i
] = AV_RL32(extradata
);
1275 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1278 if(sh_audio
->wf
->cbSize
< 22+3*4+hdrsizes
[0]+hdrsizes
[1] + hdrsizes
[2]) {
1279 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Audio header is too small !!!!!\n");
1283 // Build the ogg demuxer private datas
1284 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
1286 ogg_d
->subs
= malloc(sizeof(ogg_stream_t
));
1287 ogg_d
->subs
[0].vorbis
= 1;
1289 // Init the ogg physical stream
1290 ogg_sync_init(&ogg_d
->sync
);
1292 // Get the first page of the stream : we assume there only 1 logical stream
1293 while((np
= ogg_sync_pageout(&ogg_d
->sync
,&ogg_d
->page
)) <= 0 ) {
1295 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg error : Can't init using first stream packets\n");
1300 plen
= ds_get_packet(demuxer
->audio
,&p
);
1301 buf
= ogg_sync_buffer(&ogg_d
->sync
,plen
);
1303 ogg_sync_wrote(&ogg_d
->sync
,plen
);
1305 // Init the logical stream
1306 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d
->page
));
1307 ogg_stream_init(&ogg_d
->subs
[0].stream
,ogg_page_serialno(&ogg_d
->page
));
1309 ogg_stream_pagein(&ogg_d
->subs
[0].stream
,&ogg_d
->page
);
1311 // Create the ds_stream and the ogg demuxer
1312 s
= new_ds_stream(demuxer
->audio
);
1313 od
= new_demuxer(opts
, s
,DEMUXER_TYPE_OGG
,0,-2,-2,NULL
);
1315 /// Add the header packets in the ogg demuxer audio stream
1316 for (i
= 0; i
< 3; i
++) {
1317 dp
= new_demux_packet(hdrsizes
[i
]);
1318 memcpy(dp
->buffer
,extradata
,hdrsizes
[i
]);
1319 ds_add_packet(od
->audio
,dp
);
1320 extradata
+= hdrsizes
[i
];
1323 // Finish setting up the ogg demuxer
1325 sh_audio
= new_sh_audio(od
,0);
1328 od
->audio
->sh
= sh_audio
;
1329 sh_audio
->ds
= od
->audio
;
1330 sh_audio
->format
= FOURCC_VORBIS
;
1331 fixup_vorbis_wf(sh_audio
, ogg_d
);
1333 /// Return the joined demuxers
1334 return new_demuxers_demuxer(demuxer
,od
,demuxer
);
1337 demuxer
->audio
->id
= -2;
1342 static void demux_ogg_seek(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
) {
1343 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1344 ogg_sync_state
* sync
= &ogg_d
->sync
;
1345 ogg_page
* page
= &ogg_d
->page
;
1346 ogg_stream_state
* oss
;
1351 int i
,sp
,first
,precision
=1,do_seek
=1;
1352 vorbis_info
* vi
= NULL
;
1353 int64_t gp
= 0, old_gp
;
1360 ogg_int64_t granulepos_orig
;
1362 if(demuxer
->video
->id
>= 0) {
1363 ds
= demuxer
->video
;
1364 rate
= ogg_d
->subs
[ds
->id
].samplerate
;
1366 ds
= demuxer
->audio
;
1367 os
= &ogg_d
->subs
[ds
->id
];
1369 rate
= (float)vi
->rate
;
1370 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
1373 os
= &ogg_d
->subs
[ds
->id
];
1376 old_gp
= os
->lastpos
;
1377 old_pos
= ogg_d
->pos
;
1379 //calculate the granulepos to seek to
1380 gp
= flags
& SEEK_ABSOLUTE
? ogg_d
->initial_granulepos
: os
->lastpos
;
1381 if(flags
& SEEK_FACTOR
) {
1382 if (ogg_d
->duration
> 0)
1383 gp
+= ogg_d
->duration
* rel_seek_secs
;
1385 gp
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) * os
->lastpos
/ ogg_d
->pos
;
1387 gp
+= rel_seek_secs
* rate
;
1390 //calculate the filepos to seek to
1391 if(ogg_d
->syncpoints
) {
1392 for(sp
= 0; sp
< ogg_d
->num_syncpoint
; sp
++) {
1393 if(ogg_d
->syncpoints
[sp
].granulepos
>= gp
) break;
1396 if(sp
>= ogg_d
->num_syncpoint
) return;
1397 if (sp
> 0 && ogg_d
->syncpoints
[sp
].granulepos
- gp
> gp
- ogg_d
->syncpoints
[sp
-1].granulepos
)
1399 if (ogg_d
->syncpoints
[sp
].granulepos
== os
->lastpos
) {
1400 if (sp
> 0 && gp
< os
->lastpos
) sp
--;
1401 if (sp
< ogg_d
->num_syncpoint
-1 && gp
> os
->lastpos
) sp
++;
1403 pos
= ogg_d
->syncpoints
[sp
].page_pos
;
1406 pos
= flags
& SEEK_ABSOLUTE
? 0 : ogg_d
->pos
;
1407 if(flags
& SEEK_FACTOR
)
1408 pos
+= (demuxer
->movi_end
- demuxer
->movi_start
) * rel_seek_secs
;
1410 if (ogg_d
->duration
> 0) {
1411 pos
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) / (ogg_d
->duration
/ rate
);
1412 } else if (os
->lastpos
> 0) {
1413 pos
+= rel_seek_secs
* ogg_d
->pos
/ (os
->lastpos
/ rate
);
1416 if (pos
< 0) pos
= 0;
1417 if (pos
> (demuxer
->movi_end
- demuxer
->movi_start
))
1418 pos
= demuxer
->movi_end
- demuxer
->movi_start
;
1419 } // if(ogg_d->syncpoints)
1423 stream_seek(demuxer
->stream
,pos
+demuxer
->movi_start
);
1424 ogg_sync_reset(sync
);
1425 for(i
= 0 ; i
< ogg_d
->num_sub
; i
++) {
1426 ogg_stream_reset(&ogg_d
->subs
[i
].stream
);
1427 ogg_d
->subs
[i
].lastpos
= ogg_d
->subs
[i
].lastsize
= 0;
1430 ogg_d
->last_size
= 0;
1431 /* we just guess that we reached correct granulepos, in case a
1432 subsequent search occurs before we read a valid granulepos */
1434 first
= !(ogg_d
->syncpoints
);
1437 ogg_d
->pos
+= ogg_d
->last_size
;
1438 ogg_d
->last_size
= 0;
1439 np
= ogg_sync_pageseek(sync
,page
);
1443 if(np
<= 0) { // We need more data
1444 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
1445 int len
= stream_read(demuxer
->stream
,buf
,BLOCK_SIZE
);
1446 if(len
== 0 && demuxer
->stream
->eof
) {
1447 mp_msg(MSGT_DEMUX
,MSGL_V
,"EOF while trying to seek !!!!\n");
1450 ogg_sync_wrote(sync
,len
);
1453 ogg_d
->last_size
= np
;
1454 if(ogg_page_serialno(page
) != oss
->serialno
)
1457 if(ogg_stream_pagein(oss
,page
) != 0)
1461 np
= ogg_stream_packetout(oss
,&op
);
1466 if (first
) { /* Discard the first packet as it's probably broken,
1467 and we don't have any other means to decide whether it is
1472 is_gp_valid
= (op
.granulepos
>= 0);
1473 granulepos_orig
=op
.granulepos
;
1474 demux_ogg_read_packet(os
,&op
,&pts
,&is_keyframe
,samplesize
);
1475 if (precision
&& is_gp_valid
) {
1477 if (abs(gp
- op
.granulepos
) > rate
&& (op
.granulepos
!= old_gp
)) {
1478 //prepare another seek because we are off by more than 1s
1479 pos
+= (gp
- op
.granulepos
) * (pos
- old_pos
) / (op
.granulepos
- old_gp
);
1480 if (pos
< 0) pos
= 0;
1481 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1487 if (is_gp_valid
&& pos
> 0 && old_gp
> gp
1488 && 2 * (old_gp
- op
.granulepos
) < old_gp
- gp
) {
1489 /* prepare another seek because looking for a syncpoint
1490 destroyed the backward search */
1491 pos
= old_pos
- 1.5 * (old_pos
- pos
);
1492 if (pos
< 0) pos
= 0;
1493 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1498 if(!precision
&& (is_keyframe
|| os
->vorbis
|| os
->speex
) ) {
1499 if (sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
)) {
1501 vo_osd_changed(OSDTYPE_SUBTITLE
);
1503 op
.granulepos
=granulepos_orig
;
1504 demux_ogg_add_packet(ds
,os
,ds
->id
,&op
);
1510 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Can't find the good packet :(\n");
1514 static void demux_close_ogg(demuxer_t
* demuxer
) {
1515 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1516 ogg_stream_t
* os
= NULL
;
1526 ogg_sync_clear(&ogg_d
->sync
);
1529 for (i
= 0; i
< ogg_d
->num_sub
; i
++)
1531 os
= &ogg_d
->subs
[i
];
1532 ogg_stream_clear(&os
->stream
);
1533 if(os
->vi_initialized
)
1534 vorbis_info_clear(&os
->vi
);
1538 if(ogg_d
->syncpoints
)
1539 free(ogg_d
->syncpoints
);
1540 if (ogg_d
->text_ids
)
1541 free(ogg_d
->text_ids
);
1542 if (ogg_d
->text_langs
) {
1543 for (i
= 0; i
< ogg_d
->n_text
; i
++)
1544 if (ogg_d
->text_langs
[i
]) free(ogg_d
->text_langs
[i
]);
1545 free(ogg_d
->text_langs
);
1550 static int demux_ogg_control(demuxer_t
*demuxer
,int cmd
, void *arg
){
1551 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1555 if(demuxer
->video
->id
>= 0) {
1556 os
= &ogg_d
->subs
[demuxer
->video
->id
];
1557 rate
= os
->samplerate
;
1559 os
= &ogg_d
->subs
[demuxer
->audio
->id
];
1565 case DEMUXER_CTRL_GET_TIME_LENGTH
:
1566 if (ogg_d
->duration
<=0) return DEMUXER_CTRL_DONTKNOW
;
1567 *(double *)arg
=(double)(ogg_d
->duration
) / rate
;
1568 return DEMUXER_CTRL_GUESS
;
1570 case DEMUXER_CTRL_GET_PERCENT_POS
:
1571 if (ogg_d
->duration
<=0) return DEMUXER_CTRL_DONTKNOW
;
1572 *(int *)arg
=((os
->lastpos
- ogg_d
->initial_granulepos
)*100) / ogg_d
->duration
;
1573 return DEMUXER_CTRL_OK
;
1576 return DEMUXER_CTRL_NOTIMPL
;
1582 const demuxer_desc_t demuxer_desc_ogg
= {
1589 1, // safe autodetect
1591 demux_ogg_fill_buffer
,