13 #include "stream/stream.h"
16 #include "libavutil/intreadwrite.h"
18 #define FOURCC_VORBIS mmioFOURCC('v', 'r', 'b', 's')
19 #define FOURCC_SPEEX mmioFOURCC('s', 'p', 'x', ' ')
20 #define FOURCC_THEORA mmioFOURCC('t', 'h', 'e', 'o')
23 #include <tremor/ogg.h>
24 #include <tremor/ivorbiscodec.h>
27 #include <vorbis/codec.h>
31 #include <theora/theora.h>
32 extern int _ilog (unsigned int); /* defined in many places in theora/lib/ */
35 #define BLOCK_SIZE 4096
37 /* Theora decoder context : we won't be able to interpret granule positions
38 * without using theora_granule_time with the theora_state of the stream.
39 * This is duplicated in `vd_theora.c'; put this in a common header?
42 typedef struct theora_struct_st
{
50 // Header for the new header format
51 typedef struct stream_header_video
55 } stream_header_video
;
57 typedef struct stream_header_audio
60 ogg_int16_t blockalign
;
61 ogg_int32_t avgbytespersec
;
62 } stream_header_audio
;
64 typedef struct __attribute__((__packed__
)) stream_header
69 ogg_int32_t size
; // size of the structure
71 ogg_int64_t time_unit
; // in reference time
72 ogg_int64_t samples_per_unit
;
73 ogg_int32_t default_len
; // in media time
75 ogg_int32_t buffersize
;
76 ogg_int16_t bits_per_sample
;
83 stream_header_video video
;
85 stream_header_audio audio
;
91 typedef struct ogg_syncpoint
{
97 typedef struct ogg_stream
{
98 /// Timestamping stuff
99 float samplerate
; /// granulpos 2 time
103 // Logical stream state
104 ogg_stream_state stream
;
119 typedef struct ogg_demuxer
{
120 /// Physical stream state
127 ogg_syncpoint_t
* syncpoints
;
129 off_t pos
, last_size
;
130 int64_t final_granulepos
;
132 /* Used for subtitle switching. */
138 #define NUM_VORBIS_HDR_PACKETS 3
140 /// Some defines from OggDS
141 #define PACKET_TYPE_HEADER 0x01
142 #define PACKET_TYPE_BITS 0x07
143 #define PACKET_LEN_BITS01 0xc0
144 #define PACKET_LEN_BITS2 0x02
145 #define PACKET_IS_SYNCPOINT 0x08
147 extern char *dvdsub_lang
, *audio_lang
;
148 extern int dvdsub_id
;
150 //-------- subtitle support - should be moved to decoder layer, and queue
151 // - subtitles up in demuxer buffer...
153 #include "subreader.h"
154 #include "libvo/sub.h"
155 #define OGG_SUB_MAX_LINE 128
157 static subtitle ogg_sub
;
160 void demux_ogg_add_sub (ogg_stream_t
* os
,ogg_packet
* pack
) {
162 char *packet
= pack
->packet
;
166 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"\ndemux_ogg_add_sub %02X %02X %02X '%s'\n",
167 (unsigned char)packet
[0],
168 (unsigned char)packet
[1],
169 (unsigned char)packet
[2],
172 if (((unsigned char)packet
[0]) == 0x88) { // some subtitle text
174 double endpts
= MP_NOPTS_VALUE
;
175 int32_t duration
= 0;
176 int16_t hdrlen
= (*packet
& PACKET_LEN_BITS01
)>>6, i
;
177 hdrlen
|= (*packet
& PACKET_LEN_BITS2
) <<1;
179 if (pack
->bytes
< lcv
)
181 for (i
= hdrlen
; i
> 0; i
--) {
183 duration
|= (unsigned char)packet
[i
];
185 if (hdrlen
> 0 && duration
> 0) {
187 if(pack
->granulepos
== -1)
188 pack
->granulepos
= os
->lastpos
+ os
->lastsize
;
189 pts
= (float)pack
->granulepos
/(float)os
->samplerate
;
190 endpts
= 1.0 + pts
+ (float)duration
/1000.0;
192 sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
);
193 sub_add_text(&ogg_sub
, &packet
[lcv
], pack
->bytes
- lcv
, endpts
);
196 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg sub lines: %d first: '%s'\n",
197 ogg_sub
.lines
, ogg_sub
.text
[0]);
199 subcp_recode(&ogg_sub
);
202 vo_osd_changed(OSDTYPE_SUBTITLE
);
206 // get the logical stream of the current page
207 // fill os if non NULL and return the stream id
208 static int demux_ogg_get_page_stream(ogg_demuxer_t
* ogg_d
,ogg_stream_state
** os
) {
210 ogg_page
* page
= &ogg_d
->page
;
212 s_no
= ogg_page_serialno(page
);
214 for(id
= 0; id
< ogg_d
->num_sub
; id
++) {
215 if(s_no
== ogg_d
->subs
[id
].stream
.serialno
)
219 if(id
== ogg_d
->num_sub
) {
220 // If we have only one vorbis stream allow the stream id to change
221 // it's normal on radio stream (each song have an different id).
222 // But we (or the codec?) should check that the samplerate, etc
223 // doesn't change (for radio stream it's ok)
224 if(ogg_d
->num_sub
== 1 && ogg_d
->subs
[0].vorbis
) {
225 ogg_stream_reset(&ogg_d
->subs
[0].stream
);
226 ogg_stream_init(&ogg_d
->subs
[0].stream
,s_no
);
233 *os
= &ogg_d
->subs
[id
].stream
;
239 static unsigned char* demux_ogg_read_packet(ogg_stream_t
* os
,ogg_packet
* pack
,void *context
,float* pts
,int* flags
, int samplesize
) {
240 unsigned char* data
= pack
->packet
;
246 if(*pack
->packet
& PACKET_TYPE_HEADER
)
248 else if (os
->vi_inited
)
253 // When we dump the audio, there is no vi, but we don't care of timestamp in this case
255 blocksize
= vorbis_packet_blocksize(vi
,pack
) / samplesize
;
256 // Calculate the timestamp if the packet don't have any
257 if(pack
->granulepos
== -1) {
258 pack
->granulepos
= os
->lastpos
;
260 pack
->granulepos
+= os
->lastsize
;
262 *pts
= pack
->granulepos
/ (float)vi
->rate
;
263 os
->lastsize
= blocksize
;
264 os
->lastpos
= pack
->granulepos
;
266 } else if (os
->speex
) {
267 // whole packet (default)
268 # ifdef HAVE_OGGTHEORA
269 } else if (os
->theora
) {
270 /* we pass complete packets to theora, mustn't strip the header! */
273 /* header packets begin on 1-bit: thus check (*data&0x80). We don't
274 have theora_state st, until all header packets were passed to the
276 if (context
!= NULL
&& !(*data
&0x80))
278 theora_info
*thi
= ((theora_struct_t
*)context
)->st
.i
;
279 int keyframe_granule_shift
=_ilog(thi
->keyframe_frequency_force
-1);
280 int64_t iframemask
= (1 << keyframe_granule_shift
) - 1;
282 if (pack
->granulepos
>= 0)
284 os
->lastpos
= pack
->granulepos
>> keyframe_granule_shift
;
285 os
->lastpos
+= pack
->granulepos
& iframemask
;
286 *flags
= (pack
->granulepos
& iframemask
) == 0;
292 pack
->granulepos
= os
->lastpos
;
293 *pts
= (double)os
->lastpos
/ (double)os
->samplerate
;
295 #endif /* HAVE_OGGTHEORA */
296 } else if (os
->flac
) {
297 /* we pass complete packets to flac, mustn't strip the header! */
298 if (os
->flac
== 2 && pack
->packet
[0] != 0xff)
301 if(*pack
->packet
& PACKET_TYPE_HEADER
)
305 int16_t hdrlen
= (*pack
->packet
& PACKET_LEN_BITS01
)>>6;
306 hdrlen
|= (*pack
->packet
& PACKET_LEN_BITS2
) <<1;
307 data
= pack
->packet
+ 1 + hdrlen
;
308 // Calculate the timestamp
309 if(pack
->granulepos
== -1)
310 pack
->granulepos
= os
->lastpos
+ (os
->lastsize
? os
->lastsize
: 1);
311 // If we already have a timestamp it can be a syncpoint
312 if(*pack
->packet
& PACKET_IS_SYNCPOINT
)
314 *pts
= pack
->granulepos
/os
->samplerate
;
315 // Save the packet length and timestamp
319 os
->lastsize
|= pack
->packet
[hdrlen
];
322 os
->lastpos
= pack
->granulepos
;
328 // check if clang has substring from comma separated langlist
329 static int demux_ogg_check_lang(const char *clang
, const char *langlist
)
333 if (!langlist
|| !*langlist
)
335 while ((c
= strchr(langlist
, ',')))
337 if (!strncasecmp(clang
, langlist
, c
- langlist
))
341 if (!strncasecmp(clang
, langlist
, strlen(langlist
)))
346 static int demux_ogg_sub_reverse_id(demuxer_t
*demuxer
, int id
);
348 /// Try to print out comments and also check for LANGUAGE= tag
349 static void demux_ogg_check_comments(demuxer_t
*d
, ogg_stream_t
*os
, int id
, vorbis_comment
*vc
)
351 const char *hdr
, *val
;
352 char **cmt
= vc
->user_comments
;
354 ogg_demuxer_t
*ogg_d
= d
->priv
;
355 static const struct table
{
359 { "ENCODED_USING", "Software" },
360 { "ENCODER_URL", "Encoder URL" },
362 { "ARTIST", "Artist" },
363 { "COMMENT", "Comments" },
364 { "DATE", "Creation Date" },
365 { "GENRE", "Genre" },
366 { "ALBUM", "Album" },
367 { "TRACKNUMBER", "Track" },
374 if (!strncasecmp(*cmt
, "LANGUAGE=", 9))
377 if (ogg_d
->subs
[id
].text
)
378 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_SID_%d_LANG=%s\n", ogg_d
->subs
[id
].id
, val
);
379 else if (id
!= d
->video
->id
)
380 mp_msg(MSGT_IDENTIFY
, MSGL_INFO
, "ID_AID_%d_LANG=%s\n", ogg_d
->subs
[id
].id
, val
);
381 if (ogg_d
->subs
[id
].text
)
382 mp_msg(MSGT_DEMUX
, MSGL_INFO
, "[Ogg] Language for -sid %d is '-slang \"%s\"'\n", ogg_d
->subs
[id
].id
, val
);
383 // copy this language name into the array
384 index
= demux_ogg_sub_reverse_id(d
, id
);
386 // in case of malicious files with more than one lang per track:
387 if (ogg_d
->text_langs
[index
]) free(ogg_d
->text_langs
[index
]);
388 ogg_d
->text_langs
[index
] = strdup(val
);
390 // check for -slang if subs are uninitialized yet
391 if (os
->text
&& d
->sub
->id
< 0 && demux_ogg_check_lang(val
, dvdsub_lang
))
395 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg demuxer: Displaying subtitle stream id %d which matched -slang %s\n", id
, val
);
401 for (i
= 0; table
[i
].ogg
; i
++)
403 if (!strncasecmp(*cmt
, table
[i
].ogg
, strlen(table
[i
].ogg
)) &&
404 (*cmt
)[strlen(table
[i
].ogg
)] == '=')
407 val
= *cmt
+ strlen(table
[i
].ogg
) + 1;
412 demux_info_add(d
, hdr
, val
);
413 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, " %s: %s\n", hdr
, val
);
418 /// Calculate the timestamp and add the packet to the demux stream
419 // return 1 if the packet was added, 0 otherwise
420 static int demux_ogg_add_packet(demux_stream_t
* ds
,ogg_stream_t
* os
,int id
,ogg_packet
* pack
) {
421 demuxer_t
* d
= ds
->demuxer
;
426 void *context
= NULL
;
429 // If packet is an comment header then we try to get comments at first
430 if (pack
->bytes
>= 7 && !memcmp(pack
->packet
, "\003vorbis", 7))
435 vorbis_info_init(&vi
);
436 vorbis_comment_init(&vc
);
437 vi
.rate
= 1L; // it's checked by vorbis_synthesis_headerin()
438 if(vorbis_synthesis_headerin(&vi
, &vc
, pack
) == 0) // if no errors
439 demux_ogg_check_comments(d
, os
, id
, &vc
);
440 vorbis_comment_clear(&vc
);
441 vorbis_info_clear(&vi
);
444 if (id
== demux_ogg_sub_id(d
, d
->sub
->id
)) // don't want to add subtitles to the demuxer for now
445 demux_ogg_add_sub(os
,pack
);
449 // discard first two packets, they contain the header and comment
450 if (os
->hdr_packets
< 2) {
455 // If packet is an header we jump it except for vorbis and theora
456 // (PACKET_TYPE_HEADER bit doesn't even exist for theora ?!)
457 // We jump nothing for FLAC. Ain't this great? Packet contents have to be
458 // handled differently for each and every stream type. The joy! The joy!
459 if(!os
->flac
&& (*pack
->packet
& PACKET_TYPE_HEADER
) &&
460 (ds
!= d
->audio
|| ((sh_audio_t
*)ds
->sh
)->format
!= FOURCC_VORBIS
|| os
->hdr_packets
>= NUM_VORBIS_HDR_PACKETS
) &&
461 (ds
!= d
->video
|| (((sh_video_t
*)ds
->sh
)->format
!= FOURCC_THEORA
)))
464 // For vorbis packet the packet is the data, for other codec we must jump
466 if(ds
== d
->audio
&& ((sh_audio_t
*)ds
->sh
)->format
== FOURCC_VORBIS
) {
467 context
= ((sh_audio_t
*)ds
->sh
)->context
;
468 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
470 if (ds
== d
->video
&& ((sh_audio_t
*)ds
->sh
)->format
== FOURCC_THEORA
)
471 context
= ((sh_video_t
*)ds
->sh
)->context
;
472 data
= demux_ogg_read_packet(os
,pack
,context
,&pts
,&flags
,samplesize
);
476 /// Clear subtitles if necessary (for broken files)
477 if (sub_clear_text(&ogg_sub
, pts
)) {
479 vo_osd_changed(OSDTYPE_SUBTITLE
);
482 dp
= new_demux_packet(pack
->bytes
-(data
-pack
->packet
));
483 memcpy(dp
->buffer
,data
,pack
->bytes
-(data
-pack
->packet
));
486 ds_add_packet(ds
,dp
);
487 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"New dp: %p ds=%p pts=%5.3f len=%d flag=%d \n",
488 dp
, ds
, pts
, dp
->len
, flags
);
492 /// if -forceidx build a table of all syncpoints to make seeking easier
493 /// otherwise try to get at least the final_granulepos
494 void demux_ogg_scan_stream(demuxer_t
* demuxer
) {
495 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
496 stream_t
*s
= demuxer
->stream
;
497 ogg_sync_state
* sync
= &ogg_d
->sync
;
498 ogg_page
* page
= &ogg_d
->page
;
499 ogg_stream_state
* oss
;
502 int np
,sid
,p
,samplesize
=1;
503 void *context
= NULL
;
505 pos
= last_pos
= demuxer
->movi_start
;
508 if(index_mode
== 2) {
509 stream_seek(s
,demuxer
->movi_start
);
511 //the 270000 are just a wild guess
512 stream_seek(s
,FFMAX(ogg_d
->pos
,demuxer
->movi_end
-270000));
514 ogg_sync_reset(sync
);
516 // Get the serial number of the stream we use
517 if(demuxer
->video
->id
>= 0) {
518 sid
= demuxer
->video
->id
;
519 /* demux_ogg_read_packet needs decoder context for Theora streams */
520 if (((sh_video_t
*)demuxer
->video
->sh
)->format
== FOURCC_THEORA
)
521 context
= ((sh_video_t
*)demuxer
->video
->sh
)->context
;
523 else if(demuxer
->audio
->id
>= 0) {
524 sid
= demuxer
->audio
->id
;
525 /* demux_ogg_read_packet needs decoder context for Vorbis streams */
526 if(((sh_audio_t
*)demuxer
->audio
->sh
)->format
== FOURCC_VORBIS
) {
527 context
= ((sh_audio_t
*)demuxer
->audio
->sh
)->context
;
528 samplesize
= ((sh_audio_t
*)demuxer
->audio
->sh
)->samplesize
;
532 os
= &ogg_d
->subs
[sid
];
536 np
= ogg_sync_pageseek(sync
,page
);
537 if(np
< 0) { // We had to skip some bytes
538 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Bad page sync while building syncpoints table (%d)\n",-np
);
542 if(np
<= 0) { // We need more data
543 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
544 int len
= stream_read(s
,buf
,BLOCK_SIZE
);
545 if(len
== 0 && s
->eof
)
547 ogg_sync_wrote(sync
,len
);
551 //ogg_sync_pageout(sync,page);
552 if(ogg_page_serialno(page
) != os
->stream
.serialno
) { // It isn't a page from the stream we want
556 if(ogg_stream_pagein(oss
,page
) != 0) {
557 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Pagein error ????\n");
562 while(ogg_stream_packetout(oss
,&op
) == 1) {
565 demux_ogg_read_packet(os
,&op
,context
,&pts
,&flags
,samplesize
);
566 if(op
.granulepos
>= 0) ogg_d
->final_granulepos
= op
.granulepos
;
567 if(index_mode
== 2 && (flags
|| (os
->vorbis
&& op
.granulepos
>= 0))) {
568 if (ogg_d
->num_syncpoint
> SIZE_MAX
/ sizeof(ogg_syncpoint_t
) - 1) break;
569 ogg_d
->syncpoints
= realloc_struct(ogg_d
->syncpoints
,(ogg_d
->num_syncpoint
+1), sizeof(ogg_syncpoint_t
));
570 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].granulepos
= op
.granulepos
;
571 ogg_d
->syncpoints
[ogg_d
->num_syncpoint
].page_pos
= (ogg_page_continued(page
) && p
== 0) ? last_pos
: pos
;
572 ogg_d
->num_syncpoint
++;
576 if(p
> 1 || (p
== 1 && ! ogg_page_continued(page
)))
579 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_INFO
,"Building syncpoint table %d%%\r",(int)(pos
*100/s
->end_pos
));
581 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_INFO
,"\n");
583 if(index_mode
== 2) mp_msg(MSGT_DEMUX
,MSGL_V
,"Ogg syncpoints table builed: %d syncpoints\n",ogg_d
->num_syncpoint
);
584 mp_msg(MSGT_DEMUX
,MSGL_V
,"Ogg stream length (granulepos): %"PRId64
"\n",ogg_d
->final_granulepos
);
587 stream_seek(s
,demuxer
->movi_start
);
588 ogg_sync_reset(sync
);
589 for(np
= 0 ; np
< ogg_d
->num_sub
; np
++) {
590 ogg_stream_reset(&ogg_d
->subs
[np
].stream
);
591 ogg_d
->subs
[np
].lastpos
= ogg_d
->subs
[np
].lastsize
= ogg_d
->subs
[np
].hdr_packets
= 0;
595 // Get the first page
597 np
= ogg_sync_pageout(sync
,page
);
598 if(np
<= 0) { // We need more data
599 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
600 int len
= stream_read(s
,buf
,BLOCK_SIZE
);
601 if(len
== 0 && s
->eof
) {
602 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"EOF while trying to get the first page !!!!\n");
606 ogg_sync_wrote(sync
,len
);
609 demux_ogg_get_page_stream(ogg_d
,&oss
);
610 ogg_stream_pagein(oss
,page
);
616 extern void print_wave_header(WAVEFORMATEX
*h
, int verbose_level
);
617 extern void print_video_header(BITMAPINFOHEADER
*h
, int verbose_level
);
619 /* defined in demux_mov.c */
620 extern unsigned int store_ughvlc(unsigned char *s
, unsigned int v
);
622 /** \brief Change the current subtitle stream and return its ID.
624 \param demuxer The demuxer whose subtitle stream will be changed.
625 \param new_num The number of the new subtitle track. The number must be
626 between 0 and ogg_d->n_text - 1.
628 \returns The Ogg stream number ( = page serial number) of the newly selected
631 int demux_ogg_sub_id(demuxer_t
*demuxer
, int index
) {
632 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
633 return (index
< 0) ? index
: (index
>= ogg_d
->n_text
) ? -1 : ogg_d
->text_ids
[index
];
636 /** \brief Translate the ogg track number into the subtitle number.
637 * \param demuxer The demuxer about whose subtitles we are inquiring.
638 * \param id The ogg track number of the subtitle track.
640 static int demux_ogg_sub_reverse_id(demuxer_t
*demuxer
, int id
) {
641 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
643 for (i
= 0; i
< ogg_d
->n_text
; i
++)
644 if (ogg_d
->text_ids
[i
] == id
) return i
;
648 /** \brief Lookup the subtitle language by the subtitle number. Returns NULL on out-of-bounds input.
649 * \param demuxer The demuxer about whose subtitles we are inquiring.
650 * \param index The subtitle number.
652 const char *demux_ogg_sub_lang(demuxer_t
*demuxer
, int index
) {
653 ogg_demuxer_t
*ogg_d
= demuxer
->priv
;
654 return (index
< 0) ? NULL
: (index
>= ogg_d
->n_text
) ? NULL
: ogg_d
->text_langs
[index
];
657 static void demux_close_ogg(demuxer_t
* demuxer
);
659 static void fixup_vorbis_wf(sh_audio_t
*sh
, ogg_demuxer_t
*od
)
662 int ris
, init_error
= 0;
664 unsigned char *buf
[3];
667 ogg_stream_t
*os
= &od
->subs
[sh
->ds
->id
];
670 vorbis_info_init(&os
->vi
);
671 vorbis_comment_init(&vc
);
672 for(i
= 0; i
< 3; i
++) {
673 op
[i
].bytes
= ds_get_packet(sh
->ds
, &(op
[i
].packet
));
674 mp_msg(MSGT_DEMUX
,MSGL_V
, "fixup_vorbis_wf: i=%d, size=%ld\n", i
, op
[i
].bytes
);
675 if(op
[i
].bytes
< 0) {
676 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer error!, fixup_vorbis_wf: bad packet n. %d\n", i
);
679 buf
[i
] = malloc(op
[i
].bytes
);
682 memcpy(buf
[i
], op
[i
].packet
, op
[i
].bytes
);
684 op
[i
].b_o_s
= (i
==0);
685 ris
= vorbis_synthesis_headerin(&os
->vi
,&vc
,&op
[i
]);
688 mp_msg(MSGT_DECAUDIO
,MSGL_ERR
,"DEMUX_OGG: header n. %d broken! len=%ld, code: %d\n", i
, op
[i
].bytes
, ris
);
691 vorbis_comment_clear(&vc
);
695 len
= op
[0].bytes
+ op
[1].bytes
+ op
[2].bytes
;
696 sh
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + len
+ len
/255 + 64);
697 ptr
= (unsigned char*) (sh
->wf
+1);
701 offset
+= store_ughvlc(&ptr
[offset
], op
[0].bytes
);
702 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, offset after 1st len = %u\n", offset
);
703 offset
+= store_ughvlc(&ptr
[offset
], op
[1].bytes
);
704 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, offset after 2nd len = %u\n", offset
);
705 for(i
= 0; i
< 3; i
++) {
706 mp_msg(MSGT_DEMUX
,MSGL_V
,"demux_ogg, i=%d, bytes: %ld, offset: %u\n", i
, op
[i
].bytes
, offset
);
707 memcpy(&ptr
[offset
], buf
[i
], op
[i
].bytes
);
708 offset
+= op
[i
].bytes
;
710 sh
->wf
->cbSize
= offset
;
711 mp_msg(MSGT_DEMUX
,MSGL_V
, "demux_ogg, extradata size: %d\n", sh
->wf
->cbSize
);
712 sh
->wf
= realloc(sh
->wf
, sizeof(WAVEFORMATEX
) + sh
->wf
->cbSize
);
714 if(op
[0].bytes
>= 29) {
716 int nombr
, minbr
, maxbr
;
718 sh
->channels
= ptr
[11];
719 sh
->samplerate
= sh
->wf
->nSamplesPerSec
= AV_RL32(&ptr
[12]);
720 maxbr
= AV_RL32(&ptr
[16]); //max
721 nombr
= AV_RL32(&ptr
[20]); //nominal
722 minbr
= AV_RL32(&ptr
[24]); //minimum
736 sh
->wf
->nAvgBytesPerSec
= br
;
737 sh
->wf
->wBitsPerSample
= 16;
738 sh
->samplesize
= (sh
->wf
->wBitsPerSample
+7)/8;
740 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",
741 sh
->channels
, sh
->samplerate
, sh
->wf
->nAvgBytesPerSec
, maxbr
, nombr
, minbr
);
749 /// Open an ogg physical stream
750 // Not static because it's used also in demuxer_avi.c
751 int demux_ogg_open(demuxer_t
* demuxer
) {
752 ogg_demuxer_t
* ogg_d
;
755 int np
,s_no
, n_audio
= 0, n_video
= 0;
756 int audio_id
= -1, video_id
= -1, text_id
= -1;
757 ogg_sync_state
* sync
;
770 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
777 /// Try to get a page
778 ogg_d
->pos
+= ogg_d
->last_size
;
779 np
= ogg_sync_pageseek(sync
,page
);
782 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg demuxer : Bad page sync\n");
785 /// Need some more data
788 buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
789 len
= stream_read(s
,buf
,BLOCK_SIZE
);
790 if(len
== 0 && s
->eof
) {
793 ogg_sync_wrote(sync
,len
);
796 ogg_d
->last_size
= np
;
797 // We got one page now
799 if( ! ogg_page_bos(page
) ) { // It's not a beginning page
800 // Header parsing end here, we need to get the page otherwise it will be lost
801 int id
= demux_ogg_get_page_stream(ogg_d
,NULL
);
803 ogg_stream_pagein(&ogg_d
->subs
[id
].stream
,page
);
805 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page
));
809 /// Init the data structure needed for a logical stream
810 ogg_d
->subs
= realloc_struct(ogg_d
->subs
,ogg_d
->num_sub
+1,sizeof(ogg_stream_t
));
811 memset(&ogg_d
->subs
[ogg_d
->num_sub
],0,sizeof(ogg_stream_t
));
812 /// Get the stream serial number
813 s_no
= ogg_page_serialno(page
);
814 ogg_stream_init(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,s_no
);
815 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg : Found a stream with serial=%d\n",s_no
);
816 // Take the first page
817 ogg_stream_pagein(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,page
);
818 // Get first packet of the page
819 ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,&pack
);
825 ogg_d
->subs
[ogg_d
->num_sub
].ogg_d
= ogg_d
;
828 if(pack
.bytes
>= 7 && ! strncmp(&pack
.packet
[1],"vorbis", 6) ) {
829 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
830 sh_a
->format
= FOURCC_VORBIS
;
831 ogg_d
->subs
[ogg_d
->num_sub
].vorbis
= 1;
832 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
834 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
835 } else if (pack
.bytes
>= 80 && !strncmp(pack
.packet
,"Speex", 5)) {
836 sh_a
= new_sh_audio_aid(demuxer
, ogg_d
->num_sub
, n_audio
);
837 sh_a
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + pack
.bytes
);
838 sh_a
->format
= FOURCC_SPEEX
;
839 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(&pack
.packet
[36]);
840 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL32(&pack
.packet
[48]);
841 sh_a
->wf
->wFormatTag
= sh_a
->format
;
842 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&pack
.packet
[52]);
843 sh_a
->wf
->nBlockAlign
= 0;
844 sh_a
->wf
->wBitsPerSample
= 16;
845 sh_a
->samplesize
= 2;
846 sh_a
->wf
->cbSize
= pack
.bytes
;
847 memcpy(&sh_a
->wf
[1], pack
.packet
, pack
.bytes
);
849 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
;
850 ogg_d
->subs
[ogg_d
->num_sub
].speex
= 1;
851 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
853 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (Speex), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
856 # ifdef HAVE_OGGTHEORA
857 } else if (pack
.bytes
>= 7 && !strncmp (&pack
.packet
[1], "theora", 6)) {
862 theora_info_init (&inf
);
863 theora_comment_init (&cc
);
865 errorCode
= theora_decode_header (&inf
, &cc
, &pack
);
867 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Theora header parsing failed: %i \n",
871 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
873 sh_v
->context
= NULL
;
874 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
875 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
876 sh_v
->bih
->biCompression
= sh_v
->format
= FOURCC_THEORA
;
877 sh_v
->fps
= ((double)inf
.fps_numerator
)/
878 (double)inf
.fps_denominator
;
879 sh_v
->frametime
= ((double)inf
.fps_denominator
)/
880 (double)inf
.fps_numerator
;
881 sh_v
->disp_w
= sh_v
->bih
->biWidth
= inf
.frame_width
;
882 sh_v
->disp_h
= sh_v
->bih
->biHeight
= inf
.frame_height
;
883 sh_v
->bih
->biBitCount
= 24;
884 sh_v
->bih
->biPlanes
= 3;
885 sh_v
->bih
->biSizeImage
= ((sh_v
->bih
->biBitCount
/8) *
886 sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
);
887 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
888 ogg_d
->subs
[ogg_d
->num_sub
].theora
= 1;
889 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
891 mp_msg(MSGT_DEMUX
,MSGL_INFO
,
892 "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n",
894 (int)inf
.version_major
,
895 (int)inf
.version_minor
,
896 (int)inf
.version_subminor
,
898 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
900 theora_comment_clear(&cc
);
901 theora_info_clear(&inf
);
902 # endif /* HAVE_OGGTHEORA */
903 } else if (pack
.bytes
>= 4 && !strncmp (&pack
.packet
[0], "fLaC", 4)) {
904 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
905 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
906 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
908 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 1;
910 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
911 } else if (pack
.bytes
>= 51 && !strncmp(&pack
.packet
[1], "FLAC", 4)) {
912 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
913 sh_a
->format
= mmioFOURCC('f', 'L', 'a', 'C');
914 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
916 ogg_d
->subs
[ogg_d
->num_sub
].flac
= 2;
917 sh_a
->wf
= calloc(1, sizeof(WAVEFORMATEX
) + 34);
918 sh_a
->wf
->wFormatTag
= sh_a
->format
;
919 sh_a
->wf
->cbSize
= 34;
920 memcpy(&sh_a
->wf
[1], &pack
.packet
[17], 34);
921 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: audio (FLAC, try 2), -aid %d\n",ogg_d
->num_sub
,n_audio
-1);
923 /// Check for old header
924 } else if(pack
.bytes
>= 142 && ! strncmp(&pack
.packet
[1],"Direct Show Samples embedded in Ogg",35) ) {
927 if(AV_RL32(pack
.packet
+96) == 0x05589f80 && pack
.bytes
>= 184) {
928 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
929 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
930 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
931 sh_v
->bih
->biCompression
=
932 sh_v
->format
= mmioFOURCC(pack
.packet
[68],pack
.packet
[69],
933 pack
.packet
[70],pack
.packet
[71]);
934 sh_v
->frametime
= AV_RL64(pack
.packet
+164)*0.0000001;
935 sh_v
->fps
= 1/sh_v
->frametime
;
936 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(pack
.packet
+176);
937 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(pack
.packet
+180);
938 sh_v
->bih
->biBitCount
= AV_RL16(pack
.packet
+182);
939 if(!sh_v
->bih
->biBitCount
) sh_v
->bih
->biBitCount
=24; // hack, FIXME
940 sh_v
->bih
->biPlanes
=1;
941 sh_v
->bih
->biSizeImage
=(sh_v
->bih
->biBitCount
>>3)*sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
;
943 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
944 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
946 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
947 ogg_d
->num_sub
,pack
.packet
[68],pack
.packet
[69],pack
.packet
[70],pack
.packet
[71],n_video
-1);
948 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
950 } else if(AV_RL32(pack
.packet
+96) == 0x05589F81) {
951 unsigned int extra_size
;
952 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
953 extra_size
= AV_RL16(pack
.packet
+140);
954 sh_a
->wf
= calloc(1,sizeof(WAVEFORMATEX
)+extra_size
);
955 sh_a
->format
= sh_a
->wf
->wFormatTag
= AV_RL16(pack
.packet
+124);
956 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(pack
.packet
+126);
957 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL32(pack
.packet
+128);
958 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(pack
.packet
+132);
959 sh_a
->wf
->nBlockAlign
= AV_RL16(pack
.packet
+136);
960 sh_a
->wf
->wBitsPerSample
= AV_RL16(pack
.packet
+138);
961 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+7)/8;
962 sh_a
->wf
->cbSize
= extra_size
;
964 memcpy(((char *)sh_a
->wf
)+sizeof(WAVEFORMATEX
),pack
.packet
+142,extra_size
);
966 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
967 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
969 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);
970 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_wave_header(sh_a
->wf
,MSGL_V
);
972 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d
->num_sub
);
975 } else if ( (*pack
.packet
& PACKET_TYPE_BITS
) == PACKET_TYPE_HEADER
&&
976 pack
.bytes
>= (int)sizeof(stream_header
)+1) {
977 stream_header
*st
= (stream_header
*)(pack
.packet
+1);
979 if(strncmp(st
->streamtype
,"video",5) == 0) {
980 sh_v
= new_sh_video_vid(demuxer
,ogg_d
->num_sub
, n_video
);
981 sh_v
->bih
= calloc(1,sizeof(BITMAPINFOHEADER
));
982 sh_v
->bih
->biSize
=sizeof(BITMAPINFOHEADER
);
983 sh_v
->bih
->biCompression
=
984 sh_v
->format
= mmioFOURCC(st
->subtype
[0],st
->subtype
[1],
985 st
->subtype
[2],st
->subtype
[3]);
986 sh_v
->frametime
= AV_RL64(&st
->time_unit
)*0.0000001;
987 sh_v
->fps
= 1.0/sh_v
->frametime
;
988 sh_v
->bih
->biBitCount
= AV_RL16(&st
->bits_per_sample
);
989 sh_v
->disp_w
= sh_v
->bih
->biWidth
= AV_RL32(&st
->sh
.video
.width
);
990 sh_v
->disp_h
= sh_v
->bih
->biHeight
= AV_RL32(&st
->sh
.video
.height
);
991 if(!sh_v
->bih
->biBitCount
) sh_v
->bih
->biBitCount
=24; // hack, FIXME
992 sh_v
->bih
->biPlanes
=1;
993 sh_v
->bih
->biSizeImage
=(sh_v
->bih
->biBitCount
>>3)*sh_v
->bih
->biWidth
*sh_v
->bih
->biHeight
;
995 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_v
->fps
;
996 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_video
;
998 mp_msg(MSGT_DEMUX
,MSGL_INFO
,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n",
999 ogg_d
->num_sub
,st
->subtype
[0],st
->subtype
[1],st
->subtype
[2],st
->subtype
[3],n_video
-1);
1000 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh_v
->bih
,MSGL_V
);
1001 /// New audio header
1002 } else if(strncmp(st
->streamtype
,"audio",5) == 0) {
1004 unsigned int extra_size
= AV_RL32(&st
->size
) - sizeof(stream_header
);
1005 unsigned int extra_offset
= 0;
1007 memcpy(buffer
,st
->subtype
,4);
1010 /* Nasty workaround. stream_header.size seems not to contain the real
1011 size in all cases. There are four extra bytes that are unaccounted
1012 for in front of the real codec initialization data _at least_ for
1013 AAC. So far I've only seen those bytes being all 0, so we can
1014 just skip them here. */
1015 if ((strtol(buffer
, NULL
, 16) == 0xff) && (extra_size
>= 4)) {
1020 sh_a
= new_sh_audio_aid(demuxer
,ogg_d
->num_sub
, n_audio
);
1021 sh_a
->wf
= calloc(1,sizeof(WAVEFORMATEX
)+extra_size
);
1022 sh_a
->format
= sh_a
->wf
->wFormatTag
= strtol(buffer
, NULL
, 16);
1023 sh_a
->channels
= sh_a
->wf
->nChannels
= AV_RL16(&st
->sh
.audio
.channels
);
1024 sh_a
->samplerate
= sh_a
->wf
->nSamplesPerSec
= AV_RL64(&st
->samples_per_unit
);
1025 sh_a
->wf
->nAvgBytesPerSec
= AV_RL32(&st
->sh
.audio
.avgbytespersec
);
1026 sh_a
->wf
->nBlockAlign
= AV_RL16(&st
->sh
.audio
.blockalign
);
1027 sh_a
->wf
->wBitsPerSample
= AV_RL16(&st
->bits_per_sample
);
1028 sh_a
->samplesize
= (sh_a
->wf
->wBitsPerSample
+7)/8;
1029 sh_a
->wf
->cbSize
= extra_size
;
1031 memcpy(((char *)sh_a
->wf
)+sizeof(WAVEFORMATEX
),((char *)(st
+1))+extra_offset
,extra_size
);
1033 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= sh_a
->samplerate
; // * sh_a->channels;
1034 ogg_d
->subs
[ogg_d
->num_sub
].id
= n_audio
;
1036 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);
1037 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_wave_header(sh_a
->wf
,MSGL_V
);
1039 /// Check for text (subtitles) header
1040 } else if (strncmp(st
->streamtype
, "text", 4) == 0) {
1041 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
);
1042 ogg_d
->subs
[ogg_d
->num_sub
].samplerate
= AV_RL64(&st
->time_unit
)/10;
1043 ogg_d
->subs
[ogg_d
->num_sub
].text
= 1;
1044 ogg_d
->subs
[ogg_d
->num_sub
].id
= ogg_d
->n_text
;
1045 if (demuxer
->sub
->id
== ogg_d
->n_text
)
1046 text_id
= ogg_d
->num_sub
;
1047 new_sh_sub(demuxer
, ogg_d
->n_text
);
1049 ogg_d
->text_ids
= realloc_struct(ogg_d
->text_ids
, ogg_d
->n_text
, sizeof(int));
1050 ogg_d
->text_ids
[ogg_d
->n_text
- 1] = ogg_d
->num_sub
;
1051 ogg_d
->text_langs
= realloc_struct(ogg_d
->text_langs
, ogg_d
->n_text
, sizeof(char *));
1052 ogg_d
->text_langs
[ogg_d
->n_text
- 1] = NULL
;
1053 //// Unknown header type
1055 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d
->num_sub
);
1056 /// Unknown (invalid ?) header
1058 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg stream %d is of an unknown type\n",ogg_d
->num_sub
);
1061 demux_stream_t
* ds
= NULL
;
1063 // If the audio stream is not defined we took the first one
1064 if(demuxer
->audio
->id
== -1) {
1065 demuxer
->audio
->id
= n_audio
- 1;
1066 // if(sh_a->wf) print_wave_header(sh_a->wf,MSGL_INFO);
1068 /// Is it the stream we want
1069 if(demuxer
->audio
->id
== n_audio
- 1) {
1070 demuxer
->audio
->sh
= sh_a
;
1071 sh_a
->ds
= demuxer
->audio
;
1072 ds
= demuxer
->audio
;
1073 audio_id
= ogg_d
->num_sub
;
1078 if(demuxer
->video
->id
== -1) {
1079 demuxer
->video
->id
= n_video
- 1;
1080 // if(sh_v->bih) print_video_header(sh_v->bih,MSGL_INFO);
1082 if(demuxer
->video
->id
== n_video
- 1) {
1083 demuxer
->video
->sh
= sh_v
;
1084 sh_v
->ds
= demuxer
->video
;
1085 ds
= demuxer
->video
;
1086 video_id
= ogg_d
->num_sub
;
1089 /// Add the header packets if the stream isn't seekable
1090 if(ds
&& !s
->end_pos
) {
1091 /// Finish the page, otherwise packets will be lost
1093 demux_ogg_add_packet(ds
,&ogg_d
->subs
[ogg_d
->num_sub
],ogg_d
->num_sub
,&pack
);
1094 } while(ogg_stream_packetout(&ogg_d
->subs
[ogg_d
->num_sub
].stream
,&pack
) == 1);
1100 if(!n_video
&& !n_audio
) {
1104 if(!n_video
|| video_id
< 0)
1105 demuxer
->video
->id
= -2;
1107 demuxer
->video
->id
= video_id
;
1108 if(!n_audio
|| audio_id
< 0)
1109 demuxer
->audio
->id
= -2;
1111 demuxer
->audio
->id
= audio_id
;
1112 /* Disable the subs only if there are no text streams at all.
1113 Otherwise the stream to display might be chosen later when the comment
1114 packet is encountered and the user used -slang instead of -sid. */
1116 demuxer
->sub
->id
= -2;
1117 else if (text_id
>= 0) {
1118 demuxer
->sub
->id
= text_id
;
1119 mp_msg(MSGT_DEMUX
, MSGL_V
, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id
);
1122 ogg_d
->final_granulepos
=0;
1124 demuxer
->seekable
= 0;
1126 demuxer
->movi_start
= s
->start_pos
; // Needed for XCD (Ogg written in MODE2)
1127 demuxer
->movi_end
= s
->end_pos
;
1128 demuxer
->seekable
= 1;
1129 demux_ogg_scan_stream(demuxer
);
1132 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":"");
1134 sh_a
= demuxer
->audio
->sh
;
1136 if(sh_a
->format
== FOURCC_VORBIS
)
1137 fixup_vorbis_wf(sh_a
, ogg_d
);
1139 return DEMUXER_TYPE_OGG
;
1146 static int demux_ogg_fill_buffer(demuxer_t
*d
, demux_stream_t
*dsds
) {
1147 ogg_demuxer_t
* ogg_d
;
1150 ogg_sync_state
* sync
;
1151 ogg_stream_state
* os
;
1158 sync
= &ogg_d
->sync
;
1159 page
= &ogg_d
->page
;
1161 /// Find the stream we are working on
1162 if ( (id
= demux_ogg_get_page_stream(ogg_d
,&os
)) < 0) {
1163 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer : can't get current stream\n");
1170 /// Try to get some packet from the current page
1171 while( (np
= ogg_stream_packetout(os
,&pack
)) != 1) {
1172 /// No packet we go the next page
1177 ogg_d
->pos
+= ogg_d
->last_size
;
1178 /// Get the next page from the physical stream
1179 while( (pa
= ogg_sync_pageseek(sync
,page
)) <= 0) {
1180 /// Error : we skip some bytes
1182 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg : Page out not synced, we skip some bytes\n");
1186 /// We need more data
1187 buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
1188 len
= stream_read(s
,buf
,BLOCK_SIZE
);
1189 if(len
== 0 && s
->eof
) {
1190 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"Ogg : Stream EOF !!!!\n");
1193 ogg_sync_wrote(sync
,len
);
1195 ogg_d
->last_size
= pa
;
1196 /// Find the page's logical stream
1197 if( (id
= demux_ogg_get_page_stream(ogg_d
,&os
)) < 0) {
1198 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Ogg demuxer error : we met an unknown stream\n");
1202 if(ogg_stream_pagein(os
,page
) == 0)
1204 /// Page was invalid => retry
1205 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg demuxer : got invalid page !!!!!\n");
1206 ogg_d
->pos
+= ogg_d
->last_size
;
1208 } else /// Packet was corrupted
1209 mp_msg(MSGT_DEMUX
,MSGL_WARN
,"Ogg : bad packet in stream %d\n",id
);
1212 /// Is the actual logical stream in use ?
1213 if(id
== d
->audio
->id
)
1215 else if(id
== d
->video
->id
)
1217 else if (ogg_d
->subs
[id
].text
)
1221 if(!demux_ogg_add_packet(ds
,&ogg_d
->subs
[id
],id
,&pack
))
1222 continue; /// Unuseful packet, get another
1223 d
->filepos
= ogg_d
->pos
;
1231 /// For avi with Ogg audio stream we have to create an ogg demuxer for this
1232 // stream, then we join the avi and ogg demuxer with a demuxers demuxer
1233 demuxer_t
* init_avi_with_ogg(demuxer_t
* demuxer
) {
1235 ogg_demuxer_t
*ogg_d
;
1237 uint32_t hdrsizes
[3];
1239 sh_audio_t
*sh_audio
= demuxer
->audio
->sh
;
1241 uint8_t *extradata
= sh_audio
->wf
+ 1;
1243 unsigned char *p
= NULL
,*buf
;
1246 /// Check that the cbSize is big enough for the following reads
1247 if(sh_audio
->wf
->cbSize
< 22+3*4) {
1248 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Initial audio header is too small !!!!!\n");
1251 /// Get the size of the 3 header packet
1253 for (i
= 0; i
< 3; i
++) {
1254 hdrsizes
[i
] = AV_RL32(extradata
);
1257 // printf("\n!!!!!! hdr sizes: %d %d %d \n",hdrsizes[0],hdrsizes[1],hdrsizes[2]);
1260 if(sh_audio
->wf
->cbSize
< 22+3*4+hdrsizes
[0]+hdrsizes
[1] + hdrsizes
[2]) {
1261 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg : Audio header is too small !!!!!\n");
1265 // Build the ogg demuxer private datas
1266 ogg_d
= calloc(1,sizeof(ogg_demuxer_t
));
1268 ogg_d
->subs
= malloc(sizeof(ogg_stream_t
));
1269 ogg_d
->subs
[0].vorbis
= 1;
1271 // Init the ogg physical stream
1272 ogg_sync_init(&ogg_d
->sync
);
1274 // Get the first page of the stream : we assume there only 1 logical stream
1275 while((np
= ogg_sync_pageout(&ogg_d
->sync
,&ogg_d
->page
)) <= 0 ) {
1277 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"AVI Ogg error : Can't init using first stream packets\n");
1282 plen
= ds_get_packet(demuxer
->audio
,&p
);
1283 buf
= ogg_sync_buffer(&ogg_d
->sync
,plen
);
1285 ogg_sync_wrote(&ogg_d
->sync
,plen
);
1287 // Init the logical stream
1288 mp_msg(MSGT_DEMUX
,MSGL_DBG2
,"AVI Ogg found page with serial %d\n",ogg_page_serialno(&ogg_d
->page
));
1289 ogg_stream_init(&ogg_d
->subs
[0].stream
,ogg_page_serialno(&ogg_d
->page
));
1291 ogg_stream_pagein(&ogg_d
->subs
[0].stream
,&ogg_d
->page
);
1293 // Create the ds_stream and the ogg demuxer
1294 s
= new_ds_stream(demuxer
->audio
);
1295 od
= new_demuxer(s
,DEMUXER_TYPE_OGG
,0,-2,-2,NULL
);
1297 /// Add the header packets in the ogg demuxer audio stream
1298 for (i
= 0; i
< 3; i
++) {
1299 dp
= new_demux_packet(hdrsizes
[i
]);
1300 memcpy(dp
->buffer
,extradata
,hdrsizes
[i
]);
1301 ds_add_packet(od
->audio
,dp
);
1302 extradata
+= hdrsizes
[i
];
1305 // Finish setting up the ogg demuxer
1307 sh_audio
= new_sh_audio(od
,0);
1310 od
->audio
->sh
= sh_audio
;
1311 sh_audio
->ds
= od
->audio
;
1312 sh_audio
->format
= FOURCC_VORBIS
;
1313 fixup_vorbis_wf(sh_audio
, ogg_d
);
1315 /// Return the joined demuxers
1316 return new_demuxers_demuxer(demuxer
,od
,demuxer
);
1319 demuxer
->audio
->id
= -2;
1324 static void demux_ogg_seek(demuxer_t
*demuxer
,float rel_seek_secs
,float audio_delay
,int flags
) {
1325 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1326 ogg_sync_state
* sync
= &ogg_d
->sync
;
1327 ogg_page
* page
= &ogg_d
->page
;
1328 ogg_stream_state
* oss
;
1333 int i
,sp
,first
,precision
=1,do_seek
=1;
1334 vorbis_info
* vi
= NULL
;
1335 int64_t gp
= 0, old_gp
;
1336 void *context
= NULL
;
1343 ogg_int64_t granulepos_orig
;
1345 if(demuxer
->video
->id
>= 0) {
1346 ds
= demuxer
->video
;
1347 /* demux_ogg_read_packet needs decoder context for Theora streams */
1348 if (((sh_video_t
*)demuxer
->video
->sh
)->format
== FOURCC_THEORA
)
1349 context
= ((sh_video_t
*)demuxer
->video
->sh
)->context
;
1350 rate
= ogg_d
->subs
[ds
->id
].samplerate
;
1352 ds
= demuxer
->audio
;
1353 os
= &ogg_d
->subs
[ds
->id
];
1354 /* demux_ogg_read_packet needs decoder context for Vorbis streams */
1355 if(((sh_audio_t
*)demuxer
->audio
->sh
)->format
== FOURCC_VORBIS
)
1356 context
= ((sh_audio_t
*)demuxer
->audio
->sh
)->context
;
1358 rate
= (float)vi
->rate
;
1359 samplesize
= ((sh_audio_t
*)ds
->sh
)->samplesize
;
1362 os
= &ogg_d
->subs
[ds
->id
];
1365 old_gp
= os
->lastpos
;
1366 old_pos
= ogg_d
->pos
;
1368 //calculate the granulepos to seek to
1369 gp
= flags
& 1 ? 0 : os
->lastpos
;
1371 if (ogg_d
->final_granulepos
> 0)
1372 gp
+= ogg_d
->final_granulepos
* rel_seek_secs
;
1374 gp
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) * os
->lastpos
/ ogg_d
->pos
;
1376 gp
+= rel_seek_secs
* rate
;
1379 //calculate the filepos to seek to
1380 if(ogg_d
->syncpoints
) {
1381 for(sp
= 0; sp
< ogg_d
->num_syncpoint
; sp
++) {
1382 if(ogg_d
->syncpoints
[sp
].granulepos
>= gp
) break;
1385 if(sp
>= ogg_d
->num_syncpoint
) return;
1386 if (sp
> 0 && ogg_d
->syncpoints
[sp
].granulepos
- gp
> gp
- ogg_d
->syncpoints
[sp
-1].granulepos
)
1388 if (ogg_d
->syncpoints
[sp
].granulepos
== os
->lastpos
) {
1389 if (sp
> 0 && gp
< os
->lastpos
) sp
--;
1390 if (sp
< ogg_d
->num_syncpoint
-1 && gp
> os
->lastpos
) sp
++;
1392 pos
= ogg_d
->syncpoints
[sp
].page_pos
;
1395 pos
= flags
& 1 ? 0 : ogg_d
->pos
;
1397 pos
+= (demuxer
->movi_end
- demuxer
->movi_start
) * rel_seek_secs
;
1399 if (ogg_d
->final_granulepos
> 0) {
1400 pos
+= rel_seek_secs
* (demuxer
->movi_end
- demuxer
->movi_start
) / (ogg_d
->final_granulepos
/ rate
);
1401 } else if (os
->lastpos
> 0) {
1402 pos
+= rel_seek_secs
* ogg_d
->pos
/ (os
->lastpos
/ rate
);
1405 if (pos
< 0) pos
= 0;
1406 if (pos
> (demuxer
->movi_end
- demuxer
->movi_start
))
1407 pos
= demuxer
->movi_end
- demuxer
->movi_start
;
1408 } // if(ogg_d->syncpoints)
1412 stream_seek(demuxer
->stream
,pos
+demuxer
->movi_start
);
1413 ogg_sync_reset(sync
);
1414 for(i
= 0 ; i
< ogg_d
->num_sub
; i
++) {
1415 ogg_stream_reset(&ogg_d
->subs
[i
].stream
);
1416 ogg_d
->subs
[i
].lastpos
= ogg_d
->subs
[i
].lastsize
= 0;
1419 ogg_d
->last_size
= 0;
1420 /* we just guess that we reached correct granulepos, in case a
1421 subsequent search occurs before we read a valid granulepos */
1423 first
= !(ogg_d
->syncpoints
);
1426 ogg_d
->pos
+= ogg_d
->last_size
;
1427 ogg_d
->last_size
= 0;
1428 np
= ogg_sync_pageseek(sync
,page
);
1432 if(np
<= 0) { // We need more data
1433 char* buf
= ogg_sync_buffer(sync
,BLOCK_SIZE
);
1434 int len
= stream_read(demuxer
->stream
,buf
,BLOCK_SIZE
);
1435 if(len
== 0 && demuxer
->stream
->eof
) {
1436 mp_msg(MSGT_DEMUX
,MSGL_V
,"EOF while trying to seek !!!!\n");
1439 ogg_sync_wrote(sync
,len
);
1442 ogg_d
->last_size
= np
;
1443 if(ogg_page_serialno(page
) != oss
->serialno
)
1446 if(ogg_stream_pagein(oss
,page
) != 0)
1450 np
= ogg_stream_packetout(oss
,&op
);
1455 if (first
) { /* Discard the first packet as it's probably broken,
1456 and we don't have any other means to decide whether it is
1461 is_gp_valid
= (op
.granulepos
>= 0);
1462 granulepos_orig
=op
.granulepos
;
1463 demux_ogg_read_packet(os
,&op
,context
,&pts
,&is_keyframe
,samplesize
);
1464 if (precision
&& is_gp_valid
) {
1466 if (abs(gp
- op
.granulepos
) > rate
&& (op
.granulepos
!= old_gp
)) {
1467 //prepare another seek because we are off by more than 1s
1468 pos
+= (gp
- op
.granulepos
) * (pos
- old_pos
) / (op
.granulepos
- old_gp
);
1469 if (pos
< 0) pos
= 0;
1470 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1476 if (is_gp_valid
&& pos
> 0 && old_gp
> gp
1477 && 2 * (old_gp
- op
.granulepos
) < old_gp
- gp
) {
1478 /* prepare another seek because looking for a syncpoint
1479 destroyed the backward search */
1480 pos
= old_pos
- 1.5 * (old_pos
- pos
);
1481 if (pos
< 0) pos
= 0;
1482 if (pos
< demuxer
->movi_end
- demuxer
->movi_start
) {
1487 if(!precision
&& (is_keyframe
|| os
->vorbis
|| os
->speex
) ) {
1488 if (sub_clear_text(&ogg_sub
, MP_NOPTS_VALUE
)) {
1490 vo_osd_changed(OSDTYPE_SUBTITLE
);
1492 op
.granulepos
=granulepos_orig
;
1493 demux_ogg_add_packet(ds
,os
,ds
->id
,&op
);
1499 mp_msg(MSGT_DEMUX
,MSGL_ERR
,"Can't find the good packet :(\n");
1503 static void demux_close_ogg(demuxer_t
* demuxer
) {
1504 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1505 ogg_stream_t
* os
= NULL
;
1515 ogg_sync_clear(&ogg_d
->sync
);
1518 for (i
= 0; i
< ogg_d
->num_sub
; i
++)
1520 os
= &ogg_d
->subs
[i
];
1521 ogg_stream_clear(&os
->stream
);
1523 vorbis_info_clear(&os
->vi
);
1527 if(ogg_d
->syncpoints
)
1528 free(ogg_d
->syncpoints
);
1529 if (ogg_d
->text_ids
)
1530 free(ogg_d
->text_ids
);
1531 if (ogg_d
->text_langs
) {
1532 for (i
= 0; i
< ogg_d
->n_text
; i
++)
1533 if (ogg_d
->text_langs
[i
]) free(ogg_d
->text_langs
[i
]);
1534 free(ogg_d
->text_langs
);
1539 static int demux_ogg_control(demuxer_t
*demuxer
,int cmd
, void *arg
){
1540 ogg_demuxer_t
* ogg_d
= demuxer
->priv
;
1544 if(demuxer
->video
->id
>= 0) {
1545 os
= &ogg_d
->subs
[demuxer
->video
->id
];
1546 rate
= os
->samplerate
;
1548 os
= &ogg_d
->subs
[demuxer
->audio
->id
];
1554 case DEMUXER_CTRL_GET_TIME_LENGTH
:
1555 if (ogg_d
->final_granulepos
<=0) return DEMUXER_CTRL_DONTKNOW
;
1556 *(double *)arg
=(double)ogg_d
->final_granulepos
/ rate
;
1557 return DEMUXER_CTRL_GUESS
;
1559 case DEMUXER_CTRL_GET_PERCENT_POS
:
1560 if (ogg_d
->final_granulepos
<=0) return DEMUXER_CTRL_DONTKNOW
;
1561 *(int *)arg
=(os
->lastpos
*100) / ogg_d
->final_granulepos
;
1562 return DEMUXER_CTRL_OK
;
1565 return DEMUXER_CTRL_NOTIMPL
;
1571 demuxer_desc_t demuxer_desc_ogg
= {
1578 1, // safe autodetect
1580 demux_ogg_fill_buffer
,