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.
28 #include <libavutil/intreadwrite.h>
33 #include "stream/stream.h"
37 #include "demux_mov.h"
38 #include "demux_ogg.h"
40 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
41 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
42 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
45 #include <tremor/ogg.h>
46 #include <tremor/ivorbiscodec.h>
49 #include <vorbis/codec.h>
52 #ifdef CONFIG_OGGTHEORA
53 #include <theora/theora.h>
54 int _ilog (unsigned int); /* defined in many places in theora/lib/ */
57 #define BLOCK_SIZE 4096
59 /* Theora decoder context : we won't be able to interpret granule positions
60 * without using theora_granule_time with the theora_state of the stream.
61 * This is duplicated in `vd_theora.c'; put this in a common header?
63 #ifdef CONFIG_OGGTHEORA
64 typedef struct theora_struct_st
{
72 // Header for the new header format
73 typedef struct stream_header_video
{
76 } stream_header_video
;
78 typedef struct stream_header_audio
{
80 ogg_int16_t blockalign
;
81 ogg_int32_t avgbytespersec
;
82 } stream_header_audio
;
84 typedef struct __attribute__((__packed__
)) stream_header
{
88 ogg_int32_t size
; // size of the structure
90 ogg_int64_t time_unit
; // in reference time
91 ogg_int64_t samples_per_unit
;
92 ogg_int32_t default_len
; // in media time
94 ogg_int32_t buffersize
;
95 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 //-------- subtitle support - should be moved to decoder layer, and queue
169 // - subtitles up in demuxer buffer...
171 #include "sub/subreader.h"
173 #define OGG_SUB_MAX_LINE 128
175 static subtitle ogg_sub
;
178 static void demux_ogg_add_sub(ogg_stream_t
*os
, ogg_packet
*pack
)
181 char *packet
= pack
->packet
;
185 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
186 (unsigned char)packet
[0],
187 (unsigned char)packet
[1],
188 (unsigned char)packet
[2],
191 if (((unsigned char)packet
[0]) == 0x88) { // some subtitle text
193 double endpts
= MP_NOPTS_VALUE
;
194 int32_t duration
= 0;
195 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) {
208 if (pack
->granulepos
== -1)
209 pack
->granulepos
= os
->lastpos
+ os
->lastsize
;
210 pts
= (float)pack
->granulepos
/ (float)os
->samplerate
;
211 endpts
= 1.0 + pts
+ (float)duration
/ 1000.0;
213 sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
);
214 sub_add_text(&ogg_sub
, &packet
[lcv
], pack
->bytes
- lcv
, endpts
);
217 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Ogg sub lines: %d first: '%s'\n",
218 ogg_sub
.lines
, ogg_sub
.text
[0]);
220 subcp_recode(&ogg_sub
);
223 vo_osd_changed(OSDTYPE_SUBTITLE
);
227 // get the logical stream of the current page
228 // fill os if non NULL and return the stream id
229 static int demux_ogg_get_page_stream(ogg_demuxer_t
*ogg_d
,
230 ogg_stream_state
**os
)
233 ogg_page
*page
= &ogg_d
->page
;
235 s_no
= ogg_page_serialno(page
);
237 for (id
= 0; id
< ogg_d
->num_sub
; id
++)
238 if (s_no
== ogg_d
->subs
[id
].stream
.serialno
)
241 if (id
== ogg_d
->num_sub
) {
242 // If we have only one vorbis stream allow the stream id to change
243 // it's normal on radio stream (each song have an different id).
244 // But we (or the codec?) should check that the samplerate, etc
245 // doesn't change (for radio stream it's ok)
246 if (ogg_d
->num_sub
== 1 && ogg_d
->subs
[0].vorbis
) {
247 ogg_stream_reset(&ogg_d
->subs
[0].stream
);
248 ogg_stream_init(&ogg_d
->subs
[0].stream
, s_no
);
255 *os
= &ogg_d
->subs
[id
].stream
;
260 static unsigned char *demux_ogg_read_packet(ogg_stream_t
*os
, ogg_packet
*pack
,
261 float *pts
, bool *keyframe
,
264 unsigned char *data
= pack
->packet
;
266 *pts
= MP_NOPTS_VALUE
;
270 if (*pack
->packet
& PACKET_TYPE_HEADER
) {
274 int32_t blocksize
= 0;
276 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
277 vi
= os
->vi_initialized
? &os
->vi
: NULL
;
279 blocksize
= vorbis_packet_blocksize(vi
, pack
) / samplesize
;
280 // Calculate the timestamp if the packet don't have any
281 if (pack
->granulepos
== -1) {
282 pack
->granulepos
= os
->lastpos
;
283 if (os
->lastsize
> 0)
284 pack
->granulepos
+= os
->lastsize
;
288 *pts
= pack
->granulepos
/ (float)vi
->rate
;
289 os
->lastsize
= blocksize
;
290 os
->lastpos
= pack
->granulepos
;
292 } else if (os
->speex
) {
293 // whole packet (default)
294 # ifdef CONFIG_OGGTHEORA
295 } else if (os
->theora
) {
296 /* we pass complete packets to theora, mustn't strip the header! */
299 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
300 have theora_state st, until all header packets were passed to the
302 if (!pack
->bytes
|| !(*data
&0x80)) {
303 int keyframe_granule_shift
= _ilog(os
->keyframe_frequency_force
- 1);
304 int64_t iframemask
= (1 << keyframe_granule_shift
) - 1;
306 if (pack
->granulepos
>= 0) {
307 os
->lastpos
= pack
->granulepos
>> keyframe_granule_shift
;
308 os
->lastpos
+= pack
->granulepos
& iframemask
;
309 *keyframe
= (pack
->granulepos
& iframemask
) == 0;
313 pack
->granulepos
= os
->lastpos
;
314 *pts
= (double)os
->lastpos
/ (double)os
->samplerate
;
316 #endif /* CONFIG_OGGTHEORA */
317 } else if (os
->flac
) {
318 /* we pass complete packets to flac, mustn't strip the header! */
319 if (os
->flac
== 2 && pack
->packet
[0] != 0xff)
322 if (*pack
->packet
& PACKET_TYPE_HEADER
) {
326 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
, char **langlist
)
355 for (int i
= 0; langlist
[i
]; i
++)
356 if (!strncasecmp(clang
, langlist
[i
], strlen(langlist
[i
])))
361 /** \brief Change the current subtitle stream and return its ID.
363 \param demuxer The demuxer whose subtitle stream will be changed.
364 \param new_num The number of the new subtitle track. The number must be
365 between 0 and ogg_d->n_text - 1.
367 \returns The Ogg stream number ( = page serial number) of the newly selected
370 static int demux_ogg_sub_id(demuxer_t
*demuxer
, int index
)
372 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
373 return (index
< 0) ? index
: (index
>= ogg_d
->n_text
) ? -1 : ogg_d
->text_ids
[index
];
376 /** \brief Translate the ogg track number into the subtitle number.
377 * \param demuxer The demuxer about whose subtitles we are inquiring.
378 * \param id The ogg track number of the subtitle track.
380 static int demux_ogg_sub_reverse_id(demuxer_t
*demuxer
, int id
)
382 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
385 for (i
= 0; i
< ogg_d
->n_text
; i
++)
386 if (ogg_d
->text_ids
[i
] == id
)
391 /// Try to print out comments and also check for LANGUAGE= tag
392 static void demux_ogg_check_comments(demuxer_t
*d
, ogg_stream_t
*os
,
393 int id
, vorbis_comment
*vc
)
395 const char *hdr
, *val
;
396 char **cmt
= vc
->user_comments
;
398 ogg_demuxer_t
*ogg_d
= d
->priv
;
399 static const struct table
{
403 { "ENCODED_USING", "Software" },
404 { "ENCODER_URL", "Encoder URL" },
405 { "TITLE", "Title" },
406 { "ARTIST", "Artist" },
407 { "COMMENT", "Comments" },
408 { "DATE", "Creation Date" },
409 { "GENRE", "Genre" },
410 { "ALBUM", "Album" },
411 { "TRACKNUMBER", "Track" },
417 if (!strncasecmp(*cmt
, "LANGUAGE=", 9)) {
419 if (ogg_d
->subs
[id
].text
)
420 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_SID_%d_LANG=%s\n",
421 ogg_d
->subs
[id
].id
, val
);
422 else if (id
!= d
->video
->id
)
423 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_AID_%d_LANG=%s\n",
424 ogg_d
->subs
[id
].id
, val
);
425 if (ogg_d
->subs
[id
].text
)
426 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
427 "[Ogg] Language for -sid %d is '-slang \"%s\"'\n",
428 ogg_d
->subs
[id
].id
, val
);
429 // copy this language name into the array
430 index
= demux_ogg_sub_reverse_id(d
, id
);
434 // in case of malicious files with more than one lang per track:
435 free(ogg_d
->text_langs
[index
]);
436 ogg_d
->text_langs
[index
] = strdup(val
);
437 sh
= d
->s_streams
[index
];
439 talloc_free(sh
->lang
);
440 sh
->lang
= talloc_strdup(sh
, val
);
443 // check for -slang if subs are uninitialized yet
444 if (os
->text
&& d
->sub
->id
< 0
445 && demux_ogg_check_lang(val
, d
->opts
->sub_lang
)) {
447 d
->opts
->sub_id
= index
;
448 mp_msg(MSGT_DEMUX
, MSGL_V
,
449 "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n",
456 for (i
= 0; table
[i
].ogg
; i
++) {
457 if (!strncasecmp(*cmt
, table
[i
].ogg
, strlen(table
[i
].ogg
)) &&
458 (*cmt
)[strlen(table
[i
].ogg
)] == '=') {
460 val
= *cmt
+ strlen(table
[i
].ogg
) + 1;
465 demux_info_add(d
, hdr
, val
);
466 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, " %s: %s\n", hdr
, val
);
471 /// Calculate the timestamp and add the packet to the demux stream
472 // return 1 if the packet was added, 0 otherwise
473 static int demux_ogg_add_packet(demux_stream_t
*ds
, ogg_stream_t
*os
,
474 int id
, ogg_packet
*pack
)
476 demuxer_t
*d
= ds
->demuxer
;
479 // If packet is an comment header then we try to get comments at first
480 if (pack
->bytes
>= 7 && !memcmp(pack
->packet
, "\003vorbis", 7)) {
484 vorbis_info_init(&vi
);
485 vorbis_comment_init(&vc
);
486 vi
.rate
= 1L; // it's checked by vorbis_synthesis_headerin()
487 if (vorbis_synthesis_headerin(&vi
, &vc
, pack
) == 0) // if no errors
488 demux_ogg_check_comments(d
, os
, id
, &vc
);
489 vorbis_comment_clear(&vc
);
490 vorbis_info_clear(&vi
);
493 if (id
== demux_ogg_sub_id(d
, d
->sub
->id
)) // don't want to add subtitles to the demuxer for now
494 demux_ogg_add_sub(os
, pack
);
498 // discard first two packets, they contain the header and comment
499 if (os
->hdr_packets
< 2) {
504 // If packet is an header we jump it except for vorbis and theora
505 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
506 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
507 // handled differently for each and every stream type. The joy! The joy!
508 if (!os
->flac
&& (*pack
->packet
& PACKET_TYPE_HEADER
) &&
509 (ds
!= d
->audio
|| ((sh_audio_t
*)ds
->sh
)->format
!= FOURCC_VORBIS
|| os
->hdr_packets
>= NUM_VORBIS_HDR_PACKETS
) &&
510 (ds
!= d
->video
|| (((sh_video_t
*)ds
->sh
)->format
!= FOURCC_THEORA
)))
514 // For vorbis packet the packet is the data, for other codec we must jump
516 if (ds
== d
->audio
&& ((sh_audio_t
*)ds
->sh
)->format
== FOURCC_VORBIS
) {
517 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
522 data
= demux_ogg_read_packet(os
, pack
, &pts
, &keyframe
, samplesize
);
526 /// Clear subtitles if necessary (for broken files)
527 if (sub_clear_text(&ogg_sub
, pts
)) {
529 vo_osd_changed(OSDTYPE_SUBTITLE
);
532 struct demux_packet
*dp
;
533 dp
= new_demux_packet(pack
->bytes
- (data
- pack
->packet
));
534 memcpy(dp
->buffer
, data
, pack
->bytes
- (data
- pack
->packet
));
536 dp
->keyframe
= keyframe
;
537 ds_add_packet(ds
, dp
);
538 mp_msg(MSGT_DEMUX
, MSGL_DBG2
,
539 "New dp: %p ds=%p pts=%5.3f len=%d keyframe=%d \n",
540 dp
, ds
, pts
, dp
->len
, keyframe
);
544 /// if -forceidx build a table of all syncpoints to make seeking easier
545 /// otherwise try to get at least the final_granulepos
546 static void demux_ogg_scan_stream(demuxer_t
*demuxer
)
548 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
549 stream_t
*s
= demuxer
->stream
;
550 ogg_sync_state
*sync
= &ogg_d
->sync
;
551 ogg_page
*page
= &ogg_d
->page
;
552 ogg_stream_state
*oss
;
555 int np
, sid
, p
, samplesize
= 1;
558 pos
= last_pos
= demuxer
->movi_start
;
561 stream_seek(s
, demuxer
->movi_start
);
562 ogg_sync_reset(sync
);
564 // Get the serial number of the stream we use
565 if (demuxer
->video
->id
>= 0) {
566 sid
= demuxer
->video
->id
;
567 } else if (demuxer
->audio
->id
>= 0) {
568 sid
= demuxer
->audio
->id
;
569 if (((sh_audio_t
*)demuxer
->audio
->sh
)->format
== FOURCC_VORBIS
)
570 samplesize
= ((sh_audio_t
*)demuxer
->audio
->sh
)->samplesize
;
573 os
= &ogg_d
->subs
[sid
];
577 np
= ogg_sync_pageseek(sync
, page
);
578 if (np
< 0) { // We had to skip some bytes
580 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
581 "Bad page sync while building syncpoints table (%d)\n",
586 if (np
<= 0) { // We need more data
587 char *buf
= ogg_sync_buffer(sync
, BLOCK_SIZE
);
588 int len
= stream_read(s
, buf
, BLOCK_SIZE
);
590 if (len
== 0 && s
->eof
)
592 ogg_sync_wrote(sync
, len
);
596 //ogg_sync_pageout(sync, page);
597 if (ogg_page_serialno(page
) != os
->stream
.serialno
) { // It isn't a page from the stream we want
601 if (ogg_stream_pagein(oss
, page
) != 0) {
602 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Pagein error ????\n");
607 while (ogg_stream_packetout(oss
, &op
) == 1) {
611 demux_ogg_read_packet(os
, &op
, &pts
, &keyframe
, samplesize
);
612 if (op
.granulepos
>= 0) {
613 ogg_d
->final_granulepos
= op
.granulepos
;
614 if (ogg_d
->initial_granulepos
== MP_NOPTS_VALUE
&& keyframe
) {
615 ogg_d
->initial_granulepos
= op
.granulepos
;
616 if (index_mode
!= 2 && ogg_d
->pos
< demuxer
->movi_end
- 2 * 270000) {
617 //the 270000 are just a wild guess
618 stream_seek(s
, FFMAX(ogg_d
->pos
, demuxer
->movi_end
- 270000));
619 ogg_sync_reset(sync
);
624 if (index_mode
== 2 && (keyframe
|| (os
->vorbis
&& op
.granulepos
>= 0))) {
625 if (ogg_d
->num_syncpoint
> SIZE_MAX
/ sizeof(ogg_syncpoint_t
) - 1)
627 ogg_d
->syncpoints
= realloc_struct(ogg_d
->syncpoints
, (ogg_d
->num_syncpoint
+ 1), sizeof(ogg_syncpoint_t
));
628 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].granulepos
= op
.granulepos
;
629 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].page_pos
= (ogg_page_continued(page
) && p
== 0) ? last_pos
: pos
;
630 ogg_d
->num_syncpoint
++;
634 if (p
> 1 || (p
== 1 && !ogg_page_continued(page
)))
638 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "Building syncpoint table %d%%\r",
639 (int)(pos
* 100 / s
->end_pos
));
642 if (index_mode
== 2) {
643 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "\n");
644 mp_msg(MSGT_DEMUX
, MSGL_V
,
645 "Ogg syncpoints table builed: %d syncpoints\n",
646 ogg_d
->num_syncpoint
);
649 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg stream length (granulepos): %"PRId64
"\n",
650 ogg_d
->final_granulepos
);
653 stream_seek(s
, demuxer
->movi_start
);
654 ogg_sync_reset(sync
);
655 for (np
= 0; np
< ogg_d
->num_sub
; np
++) {
656 ogg_stream_reset(&ogg_d
->subs
[np
].stream
);
657 ogg_d
->subs
[np
].lastpos
= ogg_d
->subs
[np
].lastsize
= ogg_d
->subs
[np
].hdr_packets
= 0;
660 // Get the first page
662 np
= ogg_sync_pageout(sync
, page
);
663 if (np
<= 0) { // We need more data
664 char *buf
= ogg_sync_buffer(sync
, BLOCK_SIZE
);
665 int len
= stream_read(s
, buf
, BLOCK_SIZE
);
667 if (len
== 0 && s
->eof
) {
668 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "EOF while trying to get the first page !!!!\n");
671 ogg_sync_wrote(sync
, len
);
674 demux_ogg_get_page_stream(ogg_d
, &oss
);
675 ogg_stream_pagein(oss
, page
);
680 static void fixup_vorbis_wf(sh_audio_t
*sh
, ogg_demuxer_t
*od
)
683 int ris
, init_error
= 0;
685 unsigned char *buf
[3];
688 ogg_stream_t
*os
= &od
->subs
[sh
->ds
->id
];
691 vorbis_info_init(&os
->vi
);
692 vorbis_comment_init(&vc
);
693 for (i
= 0; i
< 3; i
++) {
694 op
[i
].bytes
= ds_get_packet(sh
->ds
, &(op
[i
].packet
));
695 mp_msg(MSGT_DEMUX
, MSGL_V
, "fixup_vorbis_wf: i=%d, size=%ld\n", i
, op
[i
].bytes
);
696 if (op
[i
].bytes
< 0) {
697 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i
);
700 buf
[i
] = malloc(op
[i
].bytes
);
703 memcpy(buf
[i
], op
[i
].packet
, op
[i
].bytes
);
705 op
[i
].b_o_s
= (i
== 0);
706 ris
= vorbis_synthesis_headerin(&os
->vi
, &vc
, &op
[i
]);
709 mp_msg(MSGT_DECAUDIO
, MSGL_ERR
, "DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i
, op
[i
].bytes
, ris
);
712 vorbis_comment_clear(&vc
);
714 os
->vi_initialized
= 1;
716 len
= op
[0].bytes
+ op
[1].bytes
+ op
[2].bytes
;
717 sh
->wf
= calloc(1, sizeof(*sh
->wf
) + len
+ len
/ 255 + 64);
718 ptr
= (unsigned char*)(sh
->wf
+ 1);
722 offset
+= store_ughvlc(&ptr
[offset
], op
[0].bytes
);
723 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_ogg, offset after 1st len = %u\n", offset
);
724 offset
+= store_ughvlc(&ptr
[offset
], op
[1].bytes
);
725 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_ogg, offset after 2nd len = %u\n", offset
);
726 for (i
= 0; i
< 3; i
++) {
727 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_ogg, i=%d, bytes: %ld, offset: %u\n", i
, op
[i
].bytes
, offset
);
728 memcpy(&ptr
[offset
], buf
[i
], op
[i
].bytes
);
729 offset
+= op
[i
].bytes
;
731 sh
->wf
->cbSize
= offset
;
732 mp_msg(MSGT_DEMUX
, MSGL_V
, "demux_ogg, extradata size: %d\n", sh
->wf
->cbSize
);
733 sh
->wf
= realloc(sh
->wf
, sizeof(*sh
->wf
) + sh
->wf
->cbSize
);
735 if (op
[0].bytes
>= 29) {
737 int nombr
, minbr
, maxbr
;
740 sh
->channels
= ptr
[11];
741 sh
->samplerate
= sh
->wf
->nSamplesPerSec
= AV_RL32(&ptr
[12]);
742 maxbr
= AV_RL32(&ptr
[16]); //max
743 nombr
= AV_RL32(&ptr
[20]); //nominal
744 minbr
= AV_RL32(&ptr
[24]); //minimum
758 sh
->wf
->nAvgBytesPerSec
= br
;
759 sh
->wf
->wBitsPerSample
= 16;
760 sh
->samplesize
= (sh
->wf
->wBitsPerSample
+ 7) / 8;
762 mp_msg(MSGT_DEMUX
, MSGL_V
,
763 "demux_ogg, vorbis stream features are: channels: %d, srate: %d, bitrate: %d, max: %u, nominal: %u, min: %u\n",
764 sh
->channels
, sh
->samplerate
, sh
->wf
->nAvgBytesPerSec
,
765 maxbr
, nombr
, minbr
);
772 /// Open an ogg physical stream
773 // Not static because it's used also in demuxer_avi.c
774 int demux_ogg_open(demuxer_t
*demuxer
)
776 ogg_demuxer_t
*ogg_d
;
779 int np
, s_no
, n_audio
= 0, n_video
= 0;
780 int audio_id
= -1, video_id
= -1, text_id
= -1;
781 ogg_sync_state
*sync
;
793 demuxer
->priv
= ogg_d
= calloc(1, sizeof(*ogg_d
));
800 /// Try to get a page
801 ogg_d
->pos
+= ogg_d
->last_size
;
802 np
= ogg_sync_pageseek(sync
, page
);
805 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Ogg demuxer : Bad page sync\n");
808 /// Need some more data
812 buf
= ogg_sync_buffer(sync
, BLOCK_SIZE
);
813 len
= stream_read(s
, buf
, BLOCK_SIZE
);
814 if (len
== 0 && s
->eof
) {
817 ogg_sync_wrote(sync
, len
);
820 ogg_d
->last_size
= np
;
821 // We got one page now
823 if (!ogg_page_bos(page
)) { // It's not a beginning page
824 // Header parsing end here, we need to get the page otherwise it will be lost
825 int id
= demux_ogg_get_page_stream(ogg_d
, NULL
);
827 ogg_stream_pagein(&ogg_d
->subs
[id
].stream
, page
);
829 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
830 "Ogg : Warning found none bos page from unknown stream %d\n",
831 ogg_page_serialno(page
));
835 /// Init the data structure needed for a logical stream
836 ogg_d
->subs
= realloc_struct(ogg_d
->subs
, ogg_d
->num_sub
+1,
837 sizeof(ogg_stream_t
));
838 memset(&ogg_d
->subs
[ogg_d
->num_sub
], 0, sizeof(ogg_stream_t
));
839 /// Get the stream serial number
840 s_no
= ogg_page_serialno(page
);
841 ogg_stream_init(&ogg_d
->subs
[ogg_d
->num_sub
].stream
, s_no
);
842 mp_msg(MSGT_DEMUX
, MSGL_DBG2
,
843 "Ogg : Found a stream with serial=%d\n", s_no
);
844 // Take the first page
845 ogg_stream_pagein(&ogg_d
->subs
[ogg_d
->num_sub
].stream
, page
);
846 // Get first packet of the page
847 ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
, &pack
);
853 ogg_d
->subs
[ogg_d
->num_sub
].ogg_d
= ogg_d
;
856 if (pack
.bytes
>= 7 && !strncmp(&pack
.packet
[1], "vorbis", 6)) {
857 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
858 sh_a
->format
= FOURCC_VORBIS
;
859 ogg_d
->subs
[ogg_d
->num_sub
].vorbis
= 1;
860 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
862 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
863 "[Ogg] stream %d: audio (Vorbis), -aid %d\n",
864 ogg_d
->num_sub
, n_audio
- 1);
865 } else if (pack
.bytes
>= 80 && !strncmp(pack
.packet
, "Speex", 5)) {
866 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
867 sh_a
->wf
= calloc(1, sizeof(*sh_a
->wf
) + pack
.bytes
);
868 sh_a
->format
= FOURCC_SPEEX
;
869 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(&pack
.packet
[36]);
870 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL32(&pack
.packet
[48]);
871 sh_a
->wf
->wFormatTag
= sh_a
->format
;
872 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&pack
.packet
[52]);
873 sh_a
->wf
->nBlockAlign
= 0;
874 sh_a
->wf
->wBitsPerSample
= 16;
875 sh_a
->samplesize
= 2;
876 sh_a
->wf
->cbSize
= pack
.bytes
;
877 memcpy(&sh_a
->wf
[1], pack
.packet
, pack
.bytes
);
879 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
;
880 ogg_d
->subs
[ogg_d
->num_sub
].speex
= 1;
881 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
883 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
884 "[Ogg] stream %d: audio (Speex), -aid %d\n",
885 ogg_d
->num_sub
, n_audio
- 1);
888 #ifdef CONFIG_OGGTHEORA
889 } else if (pack
.bytes
>= 7 && !strncmp (&pack
.packet
[1], "theora", 6)) {
894 theora_info_init (&inf
);
895 theora_comment_init (&cc
);
897 errorCode
= theora_decode_header (&inf
, &cc
, &pack
);
899 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
900 "Theora header parsing failed: %i \n", errorCode
);
902 sh_v
= new_sh_video_vid(demuxer
, ogg_d
->num_sub
, n_video
);
904 sh_v
->bih
= calloc(1, sizeof(*sh_v
->bih
));
905 sh_v
->bih
->biSize
= sizeof(*sh_v
->bih
);
906 sh_v
->bih
->biCompression
= sh_v
->format
= FOURCC_THEORA
;
907 sh_v
->fps
= ((double)inf
.fps_numerator
) / (double)inf
.fps_denominator
;
908 sh_v
->frametime
= ((double)inf
.fps_denominator
) / (double)inf
.fps_numerator
;
909 sh_v
->disp_w
= sh_v
->bih
->biWidth
= inf
.frame_width
;
910 sh_v
->disp_h
= sh_v
->bih
->biHeight
= inf
.frame_height
;
911 sh_v
->bih
->biBitCount
= 24;
912 sh_v
->bih
->biPlanes
= 3;
913 sh_v
->bih
->biSizeImage
= ((sh_v
->bih
->biBitCount
/ 8) * sh_v
->bih
->biWidth
* sh_v
->bih
->biHeight
);
914 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
915 ogg_d
->subs
[ogg_d
->num_sub
].theora
= 1;
916 ogg_d
->subs
[ogg_d
->num_sub
].keyframe_frequency_force
= inf
.keyframe_frequency_force
;
917 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
919 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
920 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
922 (int)inf
.version_major
,
923 (int)inf
.version_minor
,
924 (int)inf
.version_subminor
,
926 if (mp_msg_test(MSGT_HEADER
, MSGL_V
))
927 print_video_header(sh_v
->bih
, MSGL_V
);
929 theora_comment_clear(&cc
);
930 theora_info_clear(&inf
);
931 #endif /* CONFIG_OGGTHEORA */
932 } else if (pack
.bytes
>= 4 && !strncmp (&pack
.packet
[0], "fLaC", 4)) {
933 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
934 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
935 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
937 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 1;
939 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
940 "[Ogg] stream %d: audio (FLAC), -aid %d\n",
941 ogg_d
->num_sub
, n_audio
- 1);
942 } else if (pack
.bytes
>= 51 && !strncmp(&pack
.packet
[1], "FLAC", 4)) {
943 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
944 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
945 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
947 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 2;
948 sh_a
->wf
= calloc(1, sizeof(*sh_a
->wf
) + 34);
949 sh_a
->wf
->wFormatTag
= sh_a
->format
;
950 sh_a
->wf
->cbSize
= 34;
951 memcpy(&sh_a
->wf
[1], &pack
.packet
[17], 34);
952 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
953 "[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",
954 ogg_d
->num_sub
, n_audio
- 1);
956 /// Check for old header
957 } else if (pack
.bytes
>= 142 &&
958 !strncmp(&pack
.packet
[1], "Direct Show Samples embedded in Ogg", 35)) {
961 if (AV_RL32(pack
.packet
+ 96) == 0x05589f80 && pack
.bytes
>= 184) {
962 sh_v
= new_sh_video_vid(demuxer
, ogg_d
->num_sub
, n_video
);
963 sh_v
->bih
= calloc(1, sizeof(*sh_v
->bih
));
964 sh_v
->bih
->biSize
= sizeof(*sh_v
->bih
);
965 sh_v
->bih
->biCompression
= sh_v
->format
= mmioFOURCC(pack
.packet
[68], pack
.packet
[69],
966 pack
.packet
[70], pack
.packet
[71]);
967 sh_v
->frametime
= AV_RL64(pack
.packet
+ 164) * 0.0000001;
968 sh_v
->fps
= 1 / sh_v
->frametime
;
969 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(pack
.packet
+ 176);
970 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(pack
.packet
+ 180);
971 sh_v
->bih
->biBitCount
= AV_RL16(pack
.packet
+ 182);
972 if (!sh_v
->bih
->biBitCount
)
973 sh_v
->bih
->biBitCount
= 24; // hack, FIXME
974 sh_v
->bih
->biPlanes
= 1;
975 sh_v
->bih
->biSizeImage
= (sh_v
->bih
->biBitCount
>> 3) * sh_v
->bih
->biWidth
* sh_v
->bih
->biHeight
;
977 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
978 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
980 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
981 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
982 ogg_d
->num_sub
, pack
.packet
[68], pack
.packet
[69],
983 pack
.packet
[70], pack
.packet
[71], n_video
- 1);
984 if (mp_msg_test(MSGT_HEADER
, MSGL_V
))
985 print_video_header(sh_v
->bih
, MSGL_V
);
987 } else if (AV_RL32(pack
.packet
+ 96) == 0x05589F81) {
988 unsigned int extra_size
;
990 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
991 extra_size
= AV_RL16(pack
.packet
+ 140);
992 sh_a
->wf
= calloc(1, sizeof(*sh_a
->wf
) + extra_size
);
993 sh_a
->format
= sh_a
->wf
->wFormatTag
= AV_RL16(pack
.packet
+ 124);
994 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(pack
.packet
+ 126);
995 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(pack
.packet
+ 128);
996 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(pack
.packet
+ 132);
997 sh_a
->wf
->nBlockAlign
= AV_RL16(pack
.packet
+ 136);
998 sh_a
->wf
->wBitsPerSample
= AV_RL16(pack
.packet
+ 138);
999 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+ 7) / 8;
1000 sh_a
->wf
->cbSize
= extra_size
;
1002 memcpy(sh_a
->wf
+ 1,
1003 pack
.packet
+ 142, extra_size
);
1005 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
1006 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
1008 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
1009 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1010 ogg_d
->num_sub
, sh_a
->format
, n_audio
- 1);
1011 if (mp_msg_test(MSGT_HEADER
, MSGL_V
))
1012 print_wave_header(sh_a
->wf
, MSGL_V
);
1014 mp_msg(MSGT_DEMUX
, MSGL_WARN
,
1015 "Ogg stream %d contains an old header but the header type is unknown\n",
1019 } else if ((*pack
.packet
& PACKET_TYPE_BITS
) == PACKET_TYPE_HEADER
&&
1020 pack
.bytes
>= (int)sizeof(stream_header
) + 1) {
1021 stream_header
*st
= (stream_header
*)(pack
.packet
+ 1);
1022 /// New video header
1023 if (strncmp(st
->streamtype
, "video", 5) == 0) {
1024 sh_v
= new_sh_video_vid(demuxer
, ogg_d
->num_sub
, n_video
);
1025 sh_v
->bih
= calloc(1, sizeof(*sh_v
->bih
));
1026 sh_v
->bih
->biSize
= sizeof(*sh_v
->bih
);
1027 sh_v
->bih
->biCompression
= sh_v
->format
= mmioFOURCC(st
->subtype
[0], st
->subtype
[1],
1028 st
->subtype
[2], st
->subtype
[3]);
1029 sh_v
->frametime
= AV_RL64(&st
->time_unit
) * 0.0000001;
1030 sh_v
->fps
= 1.0 / sh_v
->frametime
;
1031 sh_v
->bih
->biBitCount
= AV_RL16(&st
->bits_per_sample
);
1032 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(&st
->sh
.video
.width
);
1033 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(&st
->sh
.video
.height
);
1034 if (!sh_v
->bih
->biBitCount
)
1035 sh_v
->bih
->biBitCount
= 24; // hack, FIXME
1036 sh_v
->bih
->biPlanes
= 1;
1037 sh_v
->bih
->biSizeImage
= (sh_v
->bih
->biBitCount
>> 3) * sh_v
->bih
->biWidth
* sh_v
->bih
->biHeight
;
1039 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
1040 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
1042 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
1043 "[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
1044 ogg_d
->num_sub
, st
->subtype
[0], st
->subtype
[1],
1045 st
->subtype
[2], st
->subtype
[3], n_video
- 1);
1046 if (mp_msg_test(MSGT_HEADER
, MSGL_V
))
1047 print_video_header(sh_v
->bih
, MSGL_V
);
1048 /// New audio header
1049 } else if (strncmp(st
->streamtype
, "audio", 5) == 0) {
1051 unsigned int extra_size
= AV_RL32(&st
->size
) - sizeof(stream_header
);
1052 unsigned int extra_offset
= 0;
1054 memcpy(buffer
, st
->subtype
, 4);
1057 /* Nasty workaround. stream_header.size seems not to contain the real
1058 size in all cases. There are four extra bytes that are unaccounted
1059 for in front of the real codec initialization data _at least_ for
1060 AAC. So far I've only seen those bytes being all 0, so we can
1061 just skip them here. */
1062 if ((strtol(buffer
, NULL
, 16) == 0xff) && (extra_size
>= 4)) {
1067 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
1068 sh_a
->wf
= calloc(1, sizeof(*sh_a
->wf
) + extra_size
);
1069 sh_a
->format
= sh_a
->wf
->wFormatTag
= strtol(buffer
, NULL
, 16);
1070 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(&st
->sh
.audio
.channels
);
1071 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL64(&st
->samples_per_unit
);
1072 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&st
->sh
.audio
.avgbytespersec
);
1073 sh_a
->wf
->nBlockAlign
= AV_RL16(&st
->sh
.audio
.blockalign
);
1074 sh_a
->wf
->wBitsPerSample
= AV_RL16(&st
->bits_per_sample
);
1075 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+ 7) / 8;
1076 sh_a
->wf
->cbSize
= extra_size
;
1079 ((char *)(st
+1))+extra_offset
, extra_size
);
1081 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
1082 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
1084 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
1085 "[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",
1086 ogg_d
->num_sub
, sh_a
->format
, n_audio
- 1);
1087 if (mp_msg_test(MSGT_HEADER
, MSGL_V
))
1088 print_wave_header(sh_a
->wf
, MSGL_V
);
1090 /// Check for text (subtitles) header
1091 } else if (strncmp(st
->streamtype
, "text", 4) == 0) {
1092 mp_msg(MSGT_DEMUX
, MSGL_INFO
,
1093 "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n",
1094 ogg_d
->num_sub
, ogg_d
->n_text
);
1095 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= AV_RL64(&st
->time_unit
) / 10;
1096 ogg_d
->subs
[ogg_d
->num_sub
].text
= 1;
1097 ogg_d
->subs
[ogg_d
->num_sub
].id
= ogg_d
->n_text
;
1098 if (demuxer
->sub
->id
== ogg_d
->n_text
)
1099 text_id
= ogg_d
->num_sub
;
1100 new_sh_sub(demuxer
, ogg_d
->n_text
);
1102 ogg_d
->text_ids
= realloc_struct(ogg_d
->text_ids
, ogg_d
->n_text
, sizeof(*ogg_d
->text_ids
));
1103 ogg_d
->text_ids
[ogg_d
->n_text
- 1] = ogg_d
->num_sub
;
1104 ogg_d
->text_langs
= realloc_struct(ogg_d
->text_langs
, ogg_d
->n_text
, sizeof(*ogg_d
->text_langs
));
1105 ogg_d
->text_langs
[ogg_d
->n_text
- 1] = NULL
;
1106 //// Unknown header type
1108 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1109 "Ogg stream %d has a header marker but is of an unknown type\n",
1111 /// Unknown (invalid ?) header
1113 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1114 "Ogg stream %d is of an unknown type\n",
1118 demux_stream_t
*ds
= NULL
;
1120 // If the audio stream is not defined we took the first one
1121 if (demuxer
->audio
->id
== -1) {
1122 demuxer
->audio
->id
= n_audio
- 1;
1123 //if (sh_a->wf) print_wave_header(sh_a->wf, MSGL_INFO);
1125 /// Is it the stream we want
1126 if (demuxer
->audio
->id
== n_audio
- 1) {
1127 demuxer
->audio
->sh
= sh_a
;
1128 sh_a
->ds
= demuxer
->audio
;
1129 ds
= demuxer
->audio
;
1130 audio_id
= ogg_d
->num_sub
;
1135 if (demuxer
->video
->id
== -1) {
1136 demuxer
->video
->id
= n_video
- 1;
1137 //if (sh_v->bih) print_video_header(sh_v->bih, MSGL_INFO);
1139 if (demuxer
->video
->id
== n_video
- 1) {
1140 demuxer
->video
->sh
= sh_v
;
1141 sh_v
->ds
= demuxer
->video
;
1142 ds
= demuxer
->video
;
1143 video_id
= ogg_d
->num_sub
;
1146 /// Add the header packets if the stream isn't seekable
1147 if (ds
&& !s
->end_pos
) {
1148 /// Finish the page, otherwise packets will be lost
1150 demux_ogg_add_packet(ds
, &ogg_d
->subs
[ogg_d
->num_sub
],
1151 ogg_d
->num_sub
, &pack
);
1152 } while (ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
, &pack
) == 1);
1158 if (!n_video
&& !n_audio
) {
1162 if (!n_video
|| video_id
< 0)
1163 demuxer
->video
->id
= -2;
1165 demuxer
->video
->id
= video_id
;
1166 if (!n_audio
|| audio_id
< 0)
1167 demuxer
->audio
->id
= -2;
1169 demuxer
->audio
->id
= audio_id
;
1170 /* Disable the subs only if there are no text streams at all.
1171 Otherwise the stream to display might be chosen later when the comment
1172 packet is encountered and the user used -slang instead of -sid. */
1174 demuxer
->sub
->id
= -2;
1175 else if (text_id
>= 0) {
1176 demuxer
->sub
->id
= text_id
;
1177 mp_msg(MSGT_DEMUX
, MSGL_V
,
1178 "Ogg demuxer: Displaying subtitle stream id %d\n", text_id
);
1181 ogg_d
->final_granulepos
= 0;
1182 ogg_d
->initial_granulepos
= MP_NOPTS_VALUE
;
1184 demuxer
->seekable
= 0;
1186 demuxer
->movi_start
= s
->start_pos
; // Needed for XCD (Ogg written in MODE2)
1187 demuxer
->movi_end
= s
->end_pos
;
1188 demuxer
->seekable
= 1;
1189 demux_ogg_scan_stream(demuxer
);
1191 if (ogg_d
->initial_granulepos
== MP_NOPTS_VALUE
)
1192 ogg_d
->initial_granulepos
= 0;
1193 ogg_d
->duration
= ogg_d
->final_granulepos
- ogg_d
->initial_granulepos
;
1195 mp_msg(MSGT_DEMUX
, MSGL_V
,
1196 "Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",
1197 n_audio
, n_audio
> 1 ? "s" : "",
1198 n_video
, n_video
> 1 ? "s" : "",
1199 ogg_d
->n_text
, ogg_d
->n_text
> 1 ? "s" : "");
1201 sh_a
= demuxer
->audio
->sh
;
1202 if (sh_a
&& sh_a
->format
== FOURCC_VORBIS
)
1203 fixup_vorbis_wf(sh_a
, ogg_d
);
1205 return DEMUXER_TYPE_OGG
;
1211 static int demux_ogg_fill_buffer(demuxer_t
*d
, demux_stream_t
*dsds
)
1213 ogg_demuxer_t
*ogg_d
;
1216 ogg_sync_state
*sync
;
1217 ogg_stream_state
*os
;
1224 sync
= &ogg_d
->sync
;
1225 page
= &ogg_d
->page
;
1227 /// Find the stream we are working on
1228 if ((id
= demux_ogg_get_page_stream(ogg_d
, &os
)) < 0) {
1229 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Ogg demuxer : can't get current stream\n");
1236 /// Try to get some packet from the current page
1237 while ((np
= ogg_stream_packetout(os
, &pack
)) != 1) {
1238 /// No packet we go the next page
1244 ogg_d
->pos
+= ogg_d
->last_size
;
1245 /// Get the next page from the physical stream
1246 while ((pa
= ogg_sync_pageseek(sync
, page
)) <= 0) {
1247 /// Error : we skip some bytes
1249 mp_msg(MSGT_DEMUX
, MSGL_WARN
,
1250 "Ogg : Page out not synced, we skip some bytes\n");
1254 /// We need more data
1255 buf
= ogg_sync_buffer(sync
, BLOCK_SIZE
);
1256 len
= stream_read(s
, buf
, BLOCK_SIZE
);
1257 if (len
== 0 && s
->eof
) {
1258 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "Ogg : Stream EOF !!!!\n");
1261 ogg_sync_wrote(sync
, len
);
1263 ogg_d
->last_size
= pa
;
1264 /// Find the page's logical stream
1265 if ((id
= demux_ogg_get_page_stream(ogg_d
, &os
)) < 0) {
1266 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1267 "Ogg demuxer error : we met an unknown stream\n");
1271 if (ogg_stream_pagein(os
, page
) == 0)
1273 /// Page was invalid => retry
1274 mp_msg(MSGT_DEMUX
, MSGL_WARN
,
1275 "Ogg demuxer : got invalid page !!!!!\n");
1276 ogg_d
->pos
+= ogg_d
->last_size
;
1278 } else /// Packet was corrupted
1279 mp_msg(MSGT_DEMUX
, MSGL_WARN
,
1280 "Ogg : bad packet in stream %d\n", id
);
1283 /// Is the actual logical stream in use ?
1284 if (id
== d
->audio
->id
)
1286 else if (id
== d
->video
->id
)
1288 else if (ogg_d
->subs
[id
].text
)
1292 if (!demux_ogg_add_packet(ds
, &ogg_d
->subs
[id
], id
, &pack
))
1293 continue; /// Unuseful packet, get another
1294 d
->filepos
= ogg_d
->pos
;
1300 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1301 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1302 demuxer_t
*init_avi_with_ogg(demuxer_t
*demuxer
)
1304 struct MPOpts
*opts
= demuxer
->opts
;
1306 ogg_demuxer_t
*ogg_d
;
1308 uint32_t hdrsizes
[3];
1310 sh_audio_t
*sh_audio
= demuxer
->audio
->sh
;
1312 uint8_t *extradata
= (uint8_t *)(sh_audio
->wf
+ 1);
1314 unsigned char *p
= NULL
, *buf
;
1317 /// Check that the cbSize is big enough for the following reads
1318 if (sh_audio
->wf
->cbSize
< 22 + 3 * 4) {
1319 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1320 "AVI Ogg : Initial audio header is too small !!!!!\n");
1323 /// Get the size of the 3 header packet
1325 for (i
= 0; i
< 3; i
++) {
1326 hdrsizes
[i
] = AV_RL32(extradata
);
1329 // printf("\n!!!!!! hdr sizes: %d %d %d \n", hdrsizes[0], hdrsizes[1], hdrsizes[2]);
1332 if (sh_audio
->wf
->cbSize
< 22 + 3 * 4 + hdrsizes
[0] + hdrsizes
[1] + hdrsizes
[2]) {
1333 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1334 "AVI Ogg : Audio header is too small !!!!!\n");
1338 // Build the ogg demuxer private datas
1339 ogg_d
= calloc(1, sizeof(*ogg_d
));
1341 ogg_d
->subs
= malloc(sizeof(*ogg_d
->subs
));
1342 ogg_d
->subs
[0].vorbis
= 1;
1344 // Init the ogg physical stream
1345 ogg_sync_init(&ogg_d
->sync
);
1347 // Get the first page of the stream : we assume there only 1 logical stream
1348 while ((np
= ogg_sync_pageout(&ogg_d
->sync
, &ogg_d
->page
)) <= 0 ) {
1350 mp_msg(MSGT_DEMUX
, MSGL_ERR
,
1351 "AVI Ogg error : Can't init using first stream packets\n");
1356 plen
= ds_get_packet(demuxer
->audio
, &p
);
1357 buf
= ogg_sync_buffer(&ogg_d
->sync
, plen
);
1358 memcpy(buf
, p
, plen
);
1359 ogg_sync_wrote(&ogg_d
->sync
, plen
);
1361 // Init the logical stream
1362 mp_msg(MSGT_DEMUX
, MSGL_DBG2
,
1363 "AVI Ogg found page with serial %d\n",
1364 ogg_page_serialno(&ogg_d
->page
));
1365 ogg_stream_init(&ogg_d
->subs
[0].stream
, ogg_page_serialno(&ogg_d
->page
));
1367 ogg_stream_pagein(&ogg_d
->subs
[0].stream
, &ogg_d
->page
);
1369 // Create the ds_stream and the ogg demuxer
1370 s
= new_ds_stream(demuxer
->audio
);
1371 od
= new_demuxer(opts
, s
, DEMUXER_TYPE_OGG
, 0, -2, -2, NULL
);
1373 /// Add the header packets in the ogg demuxer audio stream
1374 for (i
= 0; i
< 3; i
++) {
1375 dp
= new_demux_packet(hdrsizes
[i
]);
1376 memcpy(dp
->buffer
, extradata
, hdrsizes
[i
]);
1377 ds_add_packet(od
->audio
, dp
);
1378 extradata
+= hdrsizes
[i
];
1381 // Finish setting up the ogg demuxer
1383 sh_audio
= new_sh_audio(od
, 0);
1386 od
->audio
->sh
= sh_audio
;
1387 sh_audio
->ds
= od
->audio
;
1388 sh_audio
->format
= FOURCC_VORBIS
;
1389 fixup_vorbis_wf(sh_audio
, ogg_d
);
1391 /// Return the joined demuxers
1392 return new_demuxers_demuxer(demuxer
, od
, demuxer
);
1395 demuxer
->audio
->id
= -2;
1400 static void demux_ogg_seek(demuxer_t
*demuxer
, float rel_seek_secs
,
1401 float audio_delay
, int flags
)
1403 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
1404 ogg_sync_state
*sync
= &ogg_d
->sync
;
1405 ogg_page
* page
= &ogg_d
->page
;
1406 ogg_stream_state
*oss
;
1411 int i
, sp
, first
= 1, precision
= 1, do_seek
= 1;
1412 vorbis_info
*vi
= NULL
;
1413 int64_t gp
= 0, old_gp
;
1420 ogg_int64_t granulepos_orig
;
1422 if (demuxer
->video
->id
>= 0) {
1423 ds
= demuxer
->video
;
1424 rate
= ogg_d
->subs
[ds
->id
].samplerate
;
1426 ds
= demuxer
->audio
;
1427 os
= &ogg_d
->subs
[ds
->id
];
1429 rate
= (float)vi
->rate
;
1430 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
1433 os
= &ogg_d
->subs
[ds
->id
];
1436 old_gp
= os
->lastpos
;
1437 old_pos
= ogg_d
->pos
;
1439 //calculate the granulepos to seek to
1440 gp
= flags
& SEEK_ABSOLUTE
? ogg_d
->initial_granulepos
: os
->lastpos
;
1441 if (flags
& SEEK_FACTOR
) {
1442 if (ogg_d
->duration
> 0)
1443 gp
+= ogg_d
->duration
* rel_seek_secs
;
1445 gp
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) * os
->lastpos
/ ogg_d
->pos
;
1447 gp
+= rel_seek_secs
* rate
;
1451 //calculate the filepos to seek to
1452 if (ogg_d
->syncpoints
) {
1453 for (sp
= 0; sp
< ogg_d
->num_syncpoint
; sp
++)
1454 if (ogg_d
->syncpoints
[sp
].granulepos
>= gp
)
1457 if (sp
>= ogg_d
->num_syncpoint
)
1459 if (sp
> 0 && ogg_d
->syncpoints
[sp
].granulepos
- gp
> gp
- ogg_d
->syncpoints
[sp
- 1].granulepos
)
1461 if (ogg_d
->syncpoints
[sp
].granulepos
== os
->lastpos
) {
1462 if (sp
> 0 && gp
< os
->lastpos
)
1464 if (sp
< ogg_d
->num_syncpoint
- 1 && gp
> os
->lastpos
)
1467 pos
= ogg_d
->syncpoints
[sp
].page_pos
;
1470 pos
= flags
& SEEK_ABSOLUTE
? 0 : ogg_d
->pos
;
1471 if (flags
& SEEK_FACTOR
)
1472 pos
+= (demuxer
->movi_end
- demuxer
->movi_start
) * rel_seek_secs
;
1474 if (ogg_d
->duration
> 0) {
1475 pos
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) / (ogg_d
->duration
/ rate
);
1476 } else if (os
->lastpos
> 0) {
1477 pos
+= rel_seek_secs
* ogg_d
->pos
/ (os
->lastpos
/ rate
);
1482 if (pos
> (demuxer
->movi_end
- demuxer
->movi_start
))
1483 pos
= demuxer
->movi_end
- demuxer
->movi_start
;
1484 } // if (ogg_d->syncpoints)
1488 stream_seek(demuxer
->stream
, pos
+demuxer
->movi_start
);
1489 ogg_sync_reset(sync
);
1490 for (i
= 0; i
< ogg_d
->num_sub
; i
++) {
1491 ogg_stream_reset(&ogg_d
->subs
[i
].stream
);
1492 ogg_d
->subs
[i
].lastpos
= ogg_d
->subs
[i
].lastsize
= 0;
1495 ogg_d
->last_size
= 0;
1496 /* we just guess that we reached correct granulepos, in case a
1497 subsequent search occurs before we read a valid granulepos */
1499 first
= !(ogg_d
->syncpoints
);
1502 ogg_d
->pos
+= ogg_d
->last_size
;
1503 ogg_d
->last_size
= 0;
1504 np
= ogg_sync_pageseek(sync
, page
);
1508 if (np
<= 0) { // We need more data
1509 char *buf
= ogg_sync_buffer(sync
, BLOCK_SIZE
);
1510 int len
= stream_read(demuxer
->stream
, buf
, BLOCK_SIZE
);
1512 if (len
== 0 && demuxer
->stream
->eof
) {
1513 mp_msg(MSGT_DEMUX
, MSGL_V
, "EOF while trying to seek !!!!\n");
1516 ogg_sync_wrote(sync
, len
);
1519 ogg_d
->last_size
= np
;
1520 if (ogg_page_serialno(page
) != oss
->serialno
)
1523 if (ogg_stream_pagein(oss
, page
) != 0)
1527 np
= ogg_stream_packetout(oss
, &op
);
1532 if (first
) { /* Discard the first packet as it's probably broken,
1533 and we don't have any other means to decide whether it is
1538 is_gp_valid
= (op
.granulepos
>= 0);
1539 granulepos_orig
=op
.granulepos
;
1540 demux_ogg_read_packet(os
, &op
, &pts
, &is_keyframe
, samplesize
);
1541 if (precision
&& is_gp_valid
) {
1543 if (abs(gp
- op
.granulepos
) > rate
&& (op
.granulepos
!= old_gp
)) {
1544 //prepare another seek because we are off by more than 1s
1545 pos
+= (gp
- op
.granulepos
) * (pos
- old_pos
) / (op
.granulepos
- old_gp
);
1548 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1554 if (is_gp_valid
&& pos
> 0 && old_gp
> gp
1555 && 2 * (old_gp
- op
.granulepos
) < old_gp
- gp
) {
1556 /* prepare another seek because looking for a syncpoint
1557 destroyed the backward search */
1558 pos
= old_pos
- 1.5 * (old_pos
- pos
);
1561 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1566 if (!precision
&& (is_keyframe
|| os
->vorbis
|| os
->speex
)) {
1567 if (sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
)) {
1569 vo_osd_changed(OSDTYPE_SUBTITLE
);
1571 op
.granulepos
=granulepos_orig
;
1572 demux_ogg_add_packet(ds
, os
, ds
->id
, &op
);
1578 mp_msg(MSGT_DEMUX
, MSGL_ERR
, "Can't find the good packet :(\n");
1581 static void demux_close_ogg(demuxer_t
*demuxer
)
1583 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
1584 ogg_stream_t
*os
= NULL
;
1594 ogg_sync_clear(&ogg_d
->sync
);
1596 for (i
= 0; i
< ogg_d
->num_sub
; i
++) {
1597 os
= &ogg_d
->subs
[i
];
1598 ogg_stream_clear(&os
->stream
);
1599 if (os
->vi_initialized
)
1600 vorbis_info_clear(&os
->vi
);
1604 free(ogg_d
->syncpoints
);
1605 free(ogg_d
->text_ids
);
1606 if (ogg_d
->text_langs
) {
1607 for (i
= 0; i
< ogg_d
->n_text
; i
++)
1608 free(ogg_d
->text_langs
[i
]);
1609 free(ogg_d
->text_langs
);
1614 static int demux_ogg_control(demuxer_t
*demuxer
, int cmd
, void *arg
)
1616 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
1620 if (demuxer
->video
->id
>= 0) {
1621 os
= &ogg_d
->subs
[demuxer
->video
->id
];
1622 rate
= os
->samplerate
;
1624 os
= &ogg_d
->subs
[demuxer
->audio
->id
];
1629 case DEMUXER_CTRL_GET_TIME_LENGTH
:
1630 if (ogg_d
->duration
<= 0)
1631 return DEMUXER_CTRL_DONTKNOW
;
1632 *(double *)arg
= (double)(ogg_d
->duration
) / rate
;
1633 return DEMUXER_CTRL_GUESS
;
1635 case DEMUXER_CTRL_GET_PERCENT_POS
:
1636 if (ogg_d
->duration
<= 0)
1637 return DEMUXER_CTRL_DONTKNOW
;
1638 *(int *)arg
= ((os
->lastpos
- ogg_d
->initial_granulepos
) * 100) / ogg_d
->duration
;
1639 return DEMUXER_CTRL_OK
;
1642 return DEMUXER_CTRL_NOTIMPL
;
1646 const demuxer_desc_t demuxer_desc_ogg
= {
1653 1, // safe autodetect
1655 demux_ogg_fill_buffer
,