1 /*****************************************************************************
2 * ogg.c : ogg stream demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2007 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8 * Andre Pang <Andre.Pang@csiro.au> (Annodex support)
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_access.h>
35 #include <vlc_demux.h>
37 #include <vlc_input.h>
41 #include <vlc_codecs.h>
44 #include "xiph_metadata.h"
49 /*****************************************************************************
51 *****************************************************************************/
52 static int Open ( vlc_object_t * );
53 static void Close( vlc_object_t * );
56 set_shortname ( "OGG" )
57 set_description( N_("OGG demuxer" ) )
58 set_category( CAT_INPUT )
59 set_subcategory( SUBCAT_INPUT_DEMUX )
60 set_capability( "demux", 50 )
61 set_callbacks( Open, Close )
66 /*****************************************************************************
67 * Definitions of structures and functions used by this plugins
68 *****************************************************************************/
70 /* OggDS headers for the new header format (used in ogm files) */
75 } stream_header_video_t;
81 ogg_int16_t blockalign;
82 ogg_int32_t avgbytespersec;
83 } stream_header_audio_t;
90 ogg_int32_t size; /* size of the structure */
92 ogg_int64_t time_unit; /* in reference time */
93 ogg_int64_t samples_per_unit;
94 ogg_int32_t default_len; /* in media time */
96 ogg_int32_t buffersize;
97 ogg_int16_t bits_per_sample;
103 stream_header_video_t video;
105 stream_header_audio_t audio;
109 #define VORBIS_HEADER_IDENTIFICATION 1
110 #define VORBIS_HEADER_COMMENT 2
111 #define VORBIS_HEADER_SETUP 3
112 #define VORBIS_HEADER_TO_FLAG(i) (1 << (i - 1))
113 #define VORBIS_HEADERS_VALID(p_stream) \
114 ((p_stream->special.vorbis.i_headers_flags & 0b111) == 0b111)
116 /*****************************************************************************
118 *****************************************************************************/
119 static int Demux ( demux_t * );
120 static int Control( demux_t *, int, va_list );
122 /* Bitstream manipulation */
123 static int Ogg_ReadPage ( demux_t *, ogg_page * );
124 static void Ogg_UpdatePCR ( demux_t *, logical_stream_t *, ogg_packet * );
125 static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet * );
126 static int Ogg_OpusPacketDuration( ogg_packet * );
127 static void Ogg_SendOrQueueBlocks( demux_t *, logical_stream_t *, block_t * );
129 static void Ogg_CreateES( demux_t *p_demux );
130 static int Ogg_BeginningOfStream( demux_t *p_demux );
131 static int Ogg_FindLogicalStreams( demux_t *p_demux );
132 static void Ogg_EndOfStream( demux_t *p_demux );
135 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream );
136 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream );
137 static void Ogg_ResetStream( logical_stream_t *p_stream );
140 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers );
142 /* Logical bitstream headers */
143 static bool Ogg_ReadDaalaHeader( logical_stream_t *, ogg_packet * );
144 static bool Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * );
145 static bool Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
146 static bool Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
147 static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * );
148 static bool Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
149 static bool Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
150 static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
151 static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
152 static bool Ogg_ReadVP8Header( demux_t *, logical_stream_t *, ogg_packet * );
153 static void Ogg_ReadSkeletonHeader( demux_t *, logical_stream_t *, ogg_packet * );
156 static void Ogg_ReadSkeletonBones( demux_t *, ogg_packet * );
157 static void Ogg_ReadSkeletonIndex( demux_t *, ogg_packet * );
158 static void Ogg_FreeSkeleton( ogg_skeleton_t * );
159 static void Ogg_ApplySkeleton( logical_stream_t * );
161 /* Special decoding */
162 static void Ogg_CleanSpecificData( logical_stream_t * );
163 #ifdef HAVE_LIBVORBIS
164 static void Ogg_DecodeVorbisHeader( logical_stream_t *, ogg_packet *, int );
167 static void fill_channels_info(audio_format_t *audio)
169 static const int pi_channels_map[9] =
173 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
174 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
175 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
176 | AOUT_CHAN_REARRIGHT,
177 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
178 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
179 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
180 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
181 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
182 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
183 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
184 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
185 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
189 unsigned chans = audio->i_channels;
190 if (chans < sizeof(pi_channels_map) / sizeof(pi_channels_map[0]))
191 audio->i_physical_channels =
192 audio->i_original_channels = pi_channels_map[chans];
195 /* Special TS value: don't send or derive any pts/pcr from it.
196 Represents TS state prior first known valid timestamp */
197 #define VLC_TS_UNKNOWN (VLC_TS_INVALID - 1)
199 /*****************************************************************************
200 * Open: initializes ogg demux structures
201 *****************************************************************************/
202 static int Open( vlc_object_t * p_this )
204 demux_t *p_demux = (demux_t *)p_this;
206 const uint8_t *p_peek;
208 /* Check if we are dealing with an ogg stream */
209 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
210 if( !p_demux->b_force && memcmp( p_peek, "OggS", 4 ) )
212 char *psz_mime = stream_ContentType( p_demux->s );
217 else if ( strcmp( psz_mime, "application/ogg" ) &&
218 strcmp( psz_mime, "video/ogg" ) &&
219 strcmp( psz_mime, "audio/ogg" ) )
228 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
232 p_sys->i_length = -1;
233 p_sys->b_preparsing_done = false;
235 stream_Control( p_demux->s, ACCESS_GET_PTS_DELAY, & p_sys->i_access_delay );
237 /* Set exported functions */
238 p_demux->pf_demux = Demux;
239 p_demux->pf_control = Control;
241 /* Initialize the Ogg physical bitstream parser */
242 ogg_sync_init( &p_sys->oy );
245 TAB_INIT( p_sys->i_seekpoints, p_sys->pp_seekpoints );
248 while ( !p_sys->b_preparsing_done && p_demux->pf_demux( p_demux ) > 0 )
254 /*****************************************************************************
255 * Close: frees unused data
256 *****************************************************************************/
257 static void Close( vlc_object_t *p_this )
259 demux_t *p_demux = (demux_t *)p_this;
260 demux_sys_t *p_sys = p_demux->p_sys ;
262 /* Cleanup the bitstream parser */
263 ogg_sync_clear( &p_sys->oy );
265 Ogg_EndOfStream( p_demux );
267 if( p_sys->p_old_stream )
268 Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
273 /*****************************************************************************
274 * Demux: reads and demuxes data packets
275 *****************************************************************************
276 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
277 *****************************************************************************/
278 static int Demux( demux_t * p_demux )
280 demux_sys_t *p_sys = p_demux->p_sys;
281 ogg_packet oggpacket;
283 bool b_skipping = false;
286 int i_active_streams = p_sys->i_streams;
287 for ( int i=0; i < p_sys->i_streams; i++ )
289 if ( p_sys->pp_stream[i]->b_finished )
293 if ( i_active_streams == 0 )
295 if ( p_sys->i_streams ) /* All finished */
297 msg_Dbg( p_demux, "end of a group of logical streams" );
298 /* We keep the ES to try reusing it in Ogg_BeginningOfStream
299 * only 1 ES is supported (common case for ogg web radio) */
300 if( p_sys->i_streams == 1 )
302 p_sys->p_old_stream = p_sys->pp_stream[0];
303 TAB_CLEAN( p_sys->i_streams, p_sys->pp_stream );
305 Ogg_EndOfStream( p_demux );
306 p_sys->b_chained_boundary = true;
309 if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS )
312 msg_Dbg( p_demux, "beginning of a group of logical streams" );
314 if ( !p_sys->b_chained_boundary )
316 /* Find the real duration */
317 stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
319 Oggseek_ProbeEnd( p_demux );
323 p_sys->b_chained_boundary = false;
327 if ( p_sys->b_preparsing_done && !p_sys->b_es_created )
329 Ogg_CreateES( p_demux );
330 p_sys->b_es_created = true;
334 * The first data page of a physical stream is stored in the relevant logical stream
335 * in Ogg_FindLogicalStreams. Therefore, we must not read a page and only update the
336 * stream it belongs to if we haven't processed this first page yet. If we do, we
337 * will only process that first page whenever we find the second page for this stream.
338 * While this is fine for Vorbis and Theora, which are continuous codecs, which means
339 * the second page will arrive real quick, this is not fine for Kate, whose second
340 * data page will typically arrive much later.
341 * This means it is now possible to seek right at the start of a stream where the last
342 * logical stream is Kate, without having to wait for the second data page to unblock
343 * the first one, which is the one that triggers the 'no more headers to backup' code.
344 * And, as we all know, seeking without having backed up all headers is bad, since the
345 * codec will fail to initialize if it's missing its headers.
347 if( !p_sys->b_page_waiting)
350 * Demux an ogg page from the stream
352 if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS )
354 /* Test for End of Stream */
355 if( ogg_page_eos( &p_sys->current_page ) )
357 /* If we delayed restarting encoders/SET_ES_FMT for more
358 * skeleton provided configuration */
359 if ( p_sys->p_skelstream )
361 if ( p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
363 msg_Dbg( p_demux, "End of Skeleton" );
364 p_sys->b_preparsing_done = true;
365 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
367 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
368 Ogg_ApplySkeleton( p_stream );
373 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
375 if ( p_sys->pp_stream[i_stream]->i_serial_no == ogg_page_serialno( &p_sys->current_page ) )
377 p_sys->pp_stream[i_stream]->b_finished = true;
385 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
387 b_skipping |= p_sys->pp_stream[i_stream]->i_skip_frames;
390 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
392 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
394 /* if we've just pulled page, look for the right logical stream */
395 if( !p_sys->b_page_waiting )
397 if( p_sys->i_streams == 1 &&
398 ogg_page_serialno( &p_sys->current_page ) != p_stream->os.serialno )
400 msg_Err( p_demux, "Broken Ogg stream (serialno) mismatch" );
401 Ogg_ResetStream( p_stream );
402 p_sys->i_nzpcr_offset = (p_sys->i_pcr >= VLC_TS_INVALID) ?
403 p_sys->i_pcr - VLC_TS_0 : 0;
404 ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) );
407 /* Does fail if serialno differs */
408 if( ogg_stream_pagein( &p_stream->os, &p_sys->current_page ) != 0 )
414 /* clear the finished flag if pages after eos (ex: after a seek) */
415 if ( ! ogg_page_eos( &p_sys->current_page ) && p_sys->p_skelstream != p_stream )
416 p_stream->b_finished = false;
419 if ( p_stream->fmt.i_cat == VIDEO_ES )
420 msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes",
421 ogg_page_pageno( &p_sys->current_page ),
422 ogg_page_granulepos( &p_sys->current_page ),
423 ogg_page_packets( &p_sys->current_page ),
424 ogg_page_continued(&p_sys->current_page),
425 p_sys->current_page.body_len )
428 if ( p_stream->i_pcr < VLC_TS_0 && ogg_page_granulepos( &p_sys->current_page ) > 0 )
431 if ( p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
432 p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
433 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
434 p_stream->fmt.i_cat == VIDEO_ES )
436 assert( p_stream->p_prepcr_blocks == NULL );
437 p_stream->i_prepcr_blocks = 0;
438 p_stream->p_prepcr_blocks = malloc( sizeof(block_t *) * ogg_page_packets( &p_sys->current_page ) );
442 while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
444 /* Read info from any secondary header packets, if there are any */
445 if( p_stream->i_secondary_header_packets > 0 )
447 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA &&
448 oggpacket.bytes >= 7 &&
449 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
451 Ogg_ReadTheoraHeader( p_stream, &oggpacket );
452 p_stream->i_secondary_header_packets = 0;
454 else if( p_stream->fmt.i_codec == VLC_CODEC_DAALA &&
455 oggpacket.bytes >= 6 &&
456 ! memcmp( oggpacket.packet, "\x80""daala", 6 ) )
458 Ogg_ReadDaalaHeader( p_stream, &oggpacket );
459 p_stream->i_secondary_header_packets = 0;
461 else if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS &&
462 oggpacket.bytes >= 7 &&
463 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
465 Ogg_ReadVorbisHeader( p_stream, &oggpacket );
466 p_stream->i_secondary_header_packets = 0;
468 else if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
470 p_stream->i_secondary_header_packets = 0;
473 /* update start of data pointer */
474 p_stream->i_data_start = stream_Tell( p_demux->s );
477 /* If any streams have i_skip_frames, only decode (pre-roll)
478 * for those streams, but don't skip headers */
479 if ( b_skipping && p_stream->i_skip_frames == 0
480 && p_stream->i_secondary_header_packets ) continue;
482 if( p_stream->b_reinit )
484 p_stream->b_reinit = false;
485 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
487 p_stream->i_skip_frames = p_stream->i_pre_skip;
491 Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
495 if ( p_stream->p_prepcr_blocks )
497 int64_t pagestamp = Oggseek_GranuleToAbsTimestamp( p_stream, ogg_page_granulepos( &p_sys->current_page ), false );
498 p_stream->i_previous_pcr = pagestamp;
499 #ifdef HAVE_LIBVORBIS
500 int i_prev_blocksize = 0;
503 for( int i=0; i<p_stream->i_prepcr_blocks; i++ )
505 block_t *p_block = p_stream->p_prepcr_blocks[i];
506 ogg_packet dumb_packet;
507 dumb_packet.bytes = p_block->i_buffer;
508 dumb_packet.packet = p_block->p_buffer;
510 switch( p_stream->fmt.i_codec )
512 case VLC_CODEC_SPEEX:
513 p_block->i_nb_samples = p_stream->special.speex.i_framesize *
514 p_stream->special.speex.i_framesperpacket;
517 p_block->i_nb_samples = Ogg_OpusPacketDuration( &dumb_packet );
519 #ifdef HAVE_LIBVORBIS
520 case VLC_CODEC_VORBIS:
522 if( !VORBIS_HEADERS_VALID(p_stream) )
524 msg_Err( p_demux, "missing vorbis headers, can't compute block size" );
527 long i_blocksize = vorbis_packet_blocksize(
528 p_stream->special.vorbis.p_info, &dumb_packet );
529 if ( i_prev_blocksize )
530 p_block->i_nb_samples = ( i_blocksize + i_prev_blocksize ) / 4;
532 p_block->i_nb_samples = i_blocksize / 2;
533 i_prev_blocksize = i_blocksize;
540 bool b_fixed = false;
541 for( int i=p_stream->i_prepcr_blocks - 1; i>=0; i-- )
543 block_t *p_block = p_stream->p_prepcr_blocks[i];
544 switch( p_stream->fmt.i_codec )
546 case VLC_CODEC_SPEEX:
548 case VLC_CODEC_VORBIS:
549 pagestamp -= CLOCK_FREQ * p_block->i_nb_samples / p_stream->f_rate;
552 p_block->i_pts = VLC_TS_INVALID;
553 p_block->i_flags |= BLOCK_FLAG_PREROLL;
556 p_block->i_pts = VLC_TS_0 + p_sys->i_nzpcr_offset + pagestamp;
560 if ( p_stream->fmt.i_cat == VIDEO_ES )
562 pagestamp = pagestamp - ( CLOCK_FREQ / p_stream->f_rate );
563 p_block->i_pts = p_sys->i_nzpcr_offset + pagestamp;
571 if ( pagestamp < 0 ) pagestamp = 0;
572 p_stream->i_pcr = VLC_TS_0 + pagestamp;
573 p_stream->i_pcr += p_sys->i_nzpcr_offset;
574 p_stream->i_previous_granulepos = ogg_page_granulepos( &p_sys->current_page );
577 FREENULL( p_stream->p_prepcr_blocks );
578 p_stream->i_prepcr_blocks = 0;
580 Ogg_SendOrQueueBlocks( p_demux, p_stream, NULL );
584 int64_t i_pagestamp = Oggseek_GranuleToAbsTimestamp( p_stream,
585 ogg_page_granulepos( &p_sys->current_page ), false );
586 if ( i_pagestamp > -1 )
588 p_stream->i_pcr = VLC_TS_0 + i_pagestamp;
589 p_stream->i_pcr += p_sys->i_nzpcr_offset;
592 if( !p_sys->b_page_waiting )
596 /* if a page was waiting, it's now processed */
597 p_sys->b_page_waiting = false;
599 if ( p_sys->p_skelstream && !p_sys->p_skelstream->b_finished )
600 p_sys->b_preparsing_done = false;
602 p_sys->b_preparsing_done = true;
604 /* We will consider the lowest PCR among tracks, because the audio core badly
605 * handles PCR rewind (mute)
607 mtime_t i_pcr_candidate = VLC_TS_INVALID;
608 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
610 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
612 if ( p_sys->b_preparsing_done && p_stream->b_initializing )
614 /* We have 1 or more streams needing more than 1 page for preparsing */
615 p_sys->b_preparsing_done = false;
618 if( p_stream->fmt.i_cat == SPU_ES )
620 if( p_stream->i_pcr < VLC_TS_0 )
622 if ( p_stream->b_finished || p_stream->b_initializing )
624 if ( p_stream->p_preparse_block )
626 if( i_pcr_candidate < VLC_TS_0
627 || p_stream->i_pcr <= i_pcr_candidate )
629 i_pcr_candidate = p_stream->i_pcr;
633 if ( i_pcr_candidate > VLC_TS_INVALID && p_sys->i_pcr != i_pcr_candidate )
635 if ( p_sys->i_streams == 1 && p_sys->i_access_delay )
637 int64_t i_pcr_jitter = i_pcr_candidate - p_sys->i_pcr;
638 if ( i_pcr_jitter > p_sys->i_pcr_jitter )
640 p_sys->i_pcr_jitter = i_pcr_jitter;
641 if ( p_sys->i_access_delay < i_pcr_jitter )
642 msg_Warn( p_demux, "Consider increasing access caching variable from %"PRId64" to >%"PRId64,
643 p_sys->i_access_delay / 1000, i_pcr_jitter / 1000 );
647 if( ! b_skipping && p_sys->b_preparsing_done )
649 p_sys->i_pcr = i_pcr_candidate;
650 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
657 static void Ogg_ResetStream( logical_stream_t *p_stream )
659 #ifdef HAVE_LIBVORBIS
660 if ( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
662 p_stream->special.vorbis.i_prev_blocksize = 0;
665 /* we'll trash all the data until we find the next pcr */
666 p_stream->b_reinit = true;
667 p_stream->i_pcr = VLC_TS_UNKNOWN;
668 p_stream->i_previous_granulepos = -1;
669 p_stream->i_previous_pcr = VLC_TS_UNKNOWN;
670 ogg_stream_reset( &p_stream->os );
671 FREENULL( p_stream->p_prepcr_blocks );
672 p_stream->i_prepcr_blocks = 0;
675 static void Ogg_ResetStreamsHelper( demux_sys_t *p_sys )
677 for( int i = 0; i < p_sys->i_streams; i++ )
678 Ogg_ResetStream( p_sys->pp_stream[i] );
680 ogg_sync_reset( &p_sys->oy );
681 p_sys->i_pcr = VLC_TS_UNKNOWN;
684 static logical_stream_t * Ogg_GetSelectedStream( demux_t *p_demux )
686 demux_sys_t *p_sys = p_demux->p_sys;
687 logical_stream_t *p_stream = NULL;
688 for( int i=0; i<p_sys->i_streams; i++ )
690 logical_stream_t *p_candidate = p_sys->pp_stream[i];
691 if ( !p_candidate->p_es ) continue;
693 bool b_selected = false;
694 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
695 p_candidate->p_es, &b_selected );
696 if ( !b_selected ) continue;
698 if ( !p_stream && p_candidate->fmt.i_cat == AUDIO_ES )
700 p_stream = p_candidate;
701 continue; /* Try to find video anyway */
704 if ( p_candidate->fmt.i_cat == VIDEO_ES )
706 p_stream = p_candidate;
713 /*****************************************************************************
715 *****************************************************************************/
716 static int Control( demux_t *p_demux, int i_query, va_list args )
718 demux_sys_t *p_sys = p_demux->p_sys;
727 p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t* );
729 vlc_meta_Merge( p_meta, p_sys->p_meta );
732 case DEMUX_HAS_UNSUPPORTED_META:
733 pb_bool = (bool*)va_arg( args, bool* );
738 pi64 = (int64_t*)va_arg( args, int64_t * );
739 *pi64 = p_sys->i_pcr;
743 i64 = (int64_t)va_arg( args, int64_t );
744 logical_stream_t *p_stream = Ogg_GetSelectedStream( p_demux );
747 msg_Err( p_demux, "No selected seekable stream found" );
750 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
751 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
753 Ogg_ResetStreamsHelper( p_sys );
754 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
761 case DEMUX_GET_ATTACHMENTS:
763 input_attachment_t ***ppp_attach =
764 (input_attachment_t***)va_arg( args, input_attachment_t*** );
765 int *pi_int = (int*)va_arg( args, int * );
767 if( p_sys->i_attachments <= 0 )
770 *pi_int = p_sys->i_attachments;
771 *ppp_attach = xmalloc( sizeof(input_attachment_t*) * p_sys->i_attachments );
772 for( int i = 0; i < p_sys->i_attachments; i++ )
773 (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
777 case DEMUX_GET_POSITION:
778 pf = (double*)va_arg( args, double * );
779 if( p_sys->i_length > 0 )
781 *pf = (double) p_sys->i_pcr /
782 (double) ( p_sys->i_length * (mtime_t)1000000 );
784 else if( stream_Size( p_demux->s ) > 0 )
786 i64 = stream_Tell( p_demux->s );
787 *pf = (double) i64 / stream_Size( p_demux->s );
792 case DEMUX_SET_POSITION:
793 /* forbid seeking if we haven't initialized all logical bitstreams yet;
794 if we allowed, some headers would not get backed up and decoder init
795 would fail, making that logical stream unusable */
796 for ( int i=0; i< p_sys->i_streams; i++ )
798 if ( p_sys->pp_stream[i]->b_initializing )
802 p_stream = Ogg_GetSelectedStream( p_demux );
805 msg_Err( p_demux, "No selected seekable stream found" );
809 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
811 f = (double)va_arg( args, double );
812 if ( p_sys->i_length <= 0 || !b /* || ! ACCESS_CAN_FASTSEEK */ )
814 Ogg_ResetStreamsHelper( p_sys );
815 Oggseek_BlindSeektoPosition( p_demux, p_stream, f, b );
819 assert( p_sys->i_length > 0 );
820 i64 = CLOCK_FREQ * p_sys->i_length * f;
821 Ogg_ResetStreamsHelper( p_sys );
822 if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, i64 ) >= 0 )
824 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
831 case DEMUX_GET_LENGTH:
832 if ( p_sys->i_length < 0 )
833 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
835 pi64 = (int64_t*)va_arg( args, int64_t * );
836 *pi64 = p_sys->i_length * 1000000;
839 case DEMUX_GET_TITLE_INFO:
841 input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
842 int *pi_int = (int*)va_arg( args, int* );
843 int *pi_title_offset = (int*)va_arg( args, int* );
844 int *pi_seekpoint_offset = (int*)va_arg( args, int* );
846 if( p_sys->i_seekpoints > 0 )
849 *ppp_title = malloc( sizeof( input_title_t* ) );
850 input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
851 for( int i = 0; i < p_sys->i_seekpoints; i++ )
853 seekpoint_t *p_seekpoint_copy = vlc_seekpoint_Duplicate( p_sys->pp_seekpoints[i] );
854 if ( likely( p_seekpoint_copy ) )
855 TAB_APPEND( p_title->i_seekpoint, p_title->seekpoint, p_seekpoint_copy );
857 *pi_title_offset = 0;
858 *pi_seekpoint_offset = 0;
862 case DEMUX_SET_TITLE:
864 const int i_title = (int)va_arg( args, int );
869 case DEMUX_SET_SEEKPOINT:
871 const int i_seekpoint = (int)va_arg( args, int );
872 if( i_seekpoint > p_sys->i_seekpoints )
875 for ( int i=0; i< p_sys->i_streams; i++ )
877 if ( p_sys->pp_stream[i]->b_initializing )
881 i64 = p_sys->pp_seekpoints[i_seekpoint]->i_time_offset;
883 p_stream = Ogg_GetSelectedStream( p_demux );
886 msg_Err( p_demux, "No selected seekable stream found" );
890 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
891 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
893 Ogg_ResetStreamsHelper( p_sys );
894 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
896 p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
897 p_demux->info.i_seekpoint = i_seekpoint;
905 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
910 /****************************************************************************
911 * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
912 ****************************************************************************
913 * Returns VLC_SUCCESS if a page has been read. An error might happen if we
914 * are at the end of stream.
915 ****************************************************************************/
916 static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
918 demux_sys_t *p_ogg = p_demux->p_sys ;
922 while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
924 p_buffer = ogg_sync_buffer( &p_ogg->oy, OGGSEEK_BYTES_TO_READ );
926 i_read = stream_Read( p_demux->s, p_buffer, OGGSEEK_BYTES_TO_READ );
930 ogg_sync_wrote( &p_ogg->oy, i_read );
936 /****************************************************************************
937 * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
939 ****************************************************************************/
940 static void Ogg_UpdatePCR( demux_t *p_demux, logical_stream_t *p_stream,
941 ogg_packet *p_oggpacket )
943 demux_sys_t *p_ogg = p_demux->p_sys;
944 p_stream->i_end_trim = 0;
946 /* Convert the granulepos into a pcr */
947 if ( p_oggpacket->granulepos == 0 )
949 /* We're in headers, and we haven't parsed 1st data packet yet */
950 // p_stream->i_pcr = VLC_TS_UNKNOWN;
952 else if( p_oggpacket->granulepos > 0 )
954 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA ||
955 p_stream->fmt.i_codec == VLC_CODEC_DAALA ||
956 p_stream->fmt.i_codec == VLC_CODEC_KATE ||
957 p_stream->fmt.i_codec == VLC_CODEC_VP8 ||
958 p_stream->fmt.i_codec == VLC_CODEC_DIRAC ||
959 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
960 (p_stream->b_oggds && p_stream->fmt.i_cat == VIDEO_ES) )
962 p_stream->i_pcr = VLC_TS_0 + Oggseek_GranuleToAbsTimestamp( p_stream,
963 p_oggpacket->granulepos, true );
964 p_stream->i_pcr += p_ogg->i_nzpcr_offset;
966 else if ( p_stream->i_previous_granulepos > 0 )
968 ogg_int64_t sample = p_stream->i_previous_granulepos;
970 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS && p_oggpacket->e_o_s )
972 int duration = Ogg_OpusPacketDuration( p_oggpacket );
975 ogg_int64_t end_sample = p_oggpacket->granulepos;
976 if( end_sample < ( sample + duration ) )
977 p_stream->i_end_trim = sample + duration - end_sample;
981 if (sample >= p_stream->i_pre_skip)
982 sample -= p_stream->i_pre_skip;
986 p_stream->i_pcr = VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
987 p_stream->i_pcr += p_ogg->i_nzpcr_offset;
991 else if ( p_oggpacket->granulepos == -1 )
994 /* no granulepos available, try to interpolate the pcr.
995 * If we can't then don't touch the old value. */
996 if( p_stream->fmt.i_cat == VIDEO_ES && p_stream->i_pcr > VLC_TS_INVALID )
998 p_stream->i_pcr += (CLOCK_FREQ / p_stream->f_rate);
1000 #ifdef HAVE_LIBVORBIS
1001 else if ( p_stream->fmt.i_codec == VLC_CODEC_VORBIS &&
1002 p_stream->special.vorbis.p_info &&
1003 VORBIS_HEADERS_VALID(p_stream) &&
1004 p_stream->i_previous_granulepos > 0 )
1006 long i_blocksize = vorbis_packet_blocksize(
1007 p_stream->special.vorbis.p_info, p_oggpacket );
1008 if ( p_stream->special.vorbis.i_prev_blocksize )
1009 i_duration = ( i_blocksize + p_stream->special.vorbis.i_prev_blocksize ) / 4;
1011 i_duration = i_blocksize / 2;
1012 p_stream->special.vorbis.i_prev_blocksize = i_blocksize;
1013 /* duration in samples per channel */
1014 p_oggpacket->granulepos = p_stream->i_previous_granulepos + i_duration;
1015 p_stream->i_pcr = p_stream->i_previous_granulepos *
1016 CLOCK_FREQ / p_stream->special.vorbis.p_info->rate;
1017 p_stream->i_pcr += p_ogg->i_nzpcr_offset;
1020 else if ( p_stream->fmt.i_codec == VLC_CODEC_SPEEX &&
1021 p_stream->i_previous_granulepos > 0 )
1023 i_duration = p_stream->special.speex.i_framesize *
1024 p_stream->special.speex.i_framesperpacket;
1025 p_oggpacket->granulepos = p_stream->i_previous_granulepos + i_duration;
1026 p_stream->i_pcr = VLC_TS_0 + Oggseek_GranuleToAbsTimestamp( p_stream,
1027 p_stream->i_previous_granulepos, false );
1028 p_stream->i_pcr += p_ogg->i_nzpcr_offset;
1030 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
1031 p_stream->i_previous_granulepos > 0 &&
1033 Ogg_OpusPacketDuration( p_oggpacket ) ) > 0 )
1036 p_oggpacket->granulepos = p_stream->i_previous_granulepos + i_duration;
1037 sample = p_stream->i_previous_granulepos;
1038 if (sample >= p_stream->i_pre_skip)
1039 sample -= p_stream->i_pre_skip;
1043 p_stream->i_pcr = VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
1044 p_stream->i_pcr += p_ogg->i_nzpcr_offset;
1046 else if( p_stream->fmt.i_bitrate && p_stream->i_pcr > VLC_TS_UNKNOWN )
1048 p_stream->i_pcr += ( CLOCK_FREQ * p_oggpacket->bytes /
1049 p_stream->fmt.i_bitrate / 8 );
1053 p_stream->i_previous_granulepos = p_oggpacket->granulepos;
1056 static void Ogg_SendOrQueueBlocks( demux_t *p_demux, logical_stream_t *p_stream,
1059 demux_sys_t *p_ogg = p_demux->p_sys;
1060 if ( !p_stream->p_es || p_stream->p_prepcr_blocks || p_stream->i_pcr == VLC_TS_UNKNOWN )
1062 if ( !p_block ) return;
1063 if ( p_stream->p_prepcr_blocks )
1065 assert( p_stream->p_prepcr_blocks );
1066 p_stream->p_prepcr_blocks[p_stream->i_prepcr_blocks++] = p_block;
1068 DemuxDebug( msg_Dbg( p_demux, "block prepcr append > pts %"PRId64" spcr %"PRId64" pcr %"PRId64,
1069 p_block->i_pts, p_stream->i_pcr, p_ogg->i_pcr ); )
1070 block_ChainAppend( & p_stream->p_preparse_block, p_block );
1074 /* Because ES creation is delayed for preparsing */
1075 mtime_t i_firstpts = VLC_TS_UNKNOWN;
1076 if ( p_stream->p_preparse_block )
1078 block_t *temp = p_stream->p_preparse_block;
1081 if ( temp && i_firstpts < VLC_TS_0 )
1082 i_firstpts = temp->i_pts;
1084 block_t *tosend = temp;
1085 temp = temp->p_next;
1086 tosend->p_next = NULL;
1088 DemuxDebug( msg_Dbg( p_demux, "block sent from preparse > pts %"PRId64" spcr %"PRId64" pcr %"PRId64,
1089 tosend->i_pts, p_stream->i_pcr, p_ogg->i_pcr ); )
1090 es_out_Send( p_demux->out, p_stream->p_es, tosend );
1092 if ( p_ogg->i_pcr < VLC_TS_0 && i_firstpts > VLC_TS_INVALID )
1094 p_ogg->i_pcr = i_firstpts;
1095 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_ogg->i_pcr );
1098 p_stream->p_preparse_block = NULL;
1103 DemuxDebug( msg_Dbg( p_demux, "block sent directly > pts %"PRId64" spcr %"PRId64" pcr %"PRId64,
1104 p_block->i_pts, p_stream->i_pcr, p_ogg->i_pcr ) );
1105 es_out_Send( p_demux->out, p_stream->p_es, p_block );
1110 /****************************************************************************
1111 * Ogg_DecodePacket: Decode an Ogg packet.
1112 ****************************************************************************/
1113 static void Ogg_DecodePacket( demux_t *p_demux,
1114 logical_stream_t *p_stream,
1115 ogg_packet *p_oggpacket )
1119 int i_header_len = 0;
1121 if( p_oggpacket->bytes >= 7 &&
1122 ! memcmp ( p_oggpacket->packet, "Annodex", 7 ) )
1124 /* it's an Annodex packet -- skip it (do nothing) */
1127 else if( p_oggpacket->bytes >= 7 &&
1128 ! memcmp ( p_oggpacket->packet, "AnxData", 7 ) )
1130 /* it's an AnxData packet -- skip it (do nothing) */
1133 else if( p_oggpacket->bytes >= 8 &&
1134 ! memcmp ( p_oggpacket->packet, "fisbone", 8 ) )
1136 Ogg_ReadSkeletonBones( p_demux, p_oggpacket );
1139 else if( p_oggpacket->bytes >= 6 &&
1140 ! memcmp ( p_oggpacket->packet, "index", 6 ) )
1142 Ogg_ReadSkeletonIndex( p_demux, p_oggpacket );
1145 else if( p_stream->fmt.i_codec == VLC_CODEC_VP8 &&
1146 p_oggpacket->bytes >= 7 &&
1147 !memcmp( p_oggpacket->packet, "OVP80\x02\x20", 7 ) )
1149 Ogg_ReadVP8Header( p_demux, p_stream, p_oggpacket );
1153 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT && p_oggpacket->bytes > 0 &&
1154 p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
1156 /* Check the ES is selected */
1157 if ( !p_stream->p_es )
1160 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
1161 p_stream->p_es, &b_selected );
1163 if( p_stream->b_force_backup )
1166 p_stream->i_packets_backup++;
1167 switch( p_stream->fmt.i_codec )
1169 case VLC_CODEC_VORBIS:
1170 #ifdef HAVE_LIBVORBIS
1171 Ogg_DecodeVorbisHeader( p_stream, p_oggpacket, p_stream->i_packets_backup );
1174 case VLC_CODEC_THEORA:
1175 if( p_stream->i_packets_backup == 3 )
1176 p_stream->b_force_backup = false;
1180 case VLC_CODEC_DAALA:
1181 if( p_stream->i_packets_backup == 3 )
1182 p_stream->b_force_backup = false;
1186 case VLC_CODEC_SPEEX:
1187 if( p_stream->i_packets_backup == 2 + p_stream->i_extra_headers_packets )
1188 p_stream->b_force_backup = false;
1192 case VLC_CODEC_OPUS:
1193 if( p_stream->i_packets_backup == 2 )
1194 p_stream->b_force_backup = false;
1198 case VLC_CODEC_FLAC:
1199 if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )
1201 Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );
1202 p_stream->b_force_backup = false;
1204 else if( p_stream->fmt.audio.i_rate )
1206 p_stream->b_force_backup = false;
1207 if( p_oggpacket->bytes >= 9 )
1209 p_oggpacket->packet += 9;
1210 p_oggpacket->bytes -= 9;
1216 case VLC_CODEC_KATE:
1217 if( p_stream->i_packets_backup == p_stream->special.kate.i_num_headers )
1218 p_stream->b_force_backup = false;
1223 p_stream->b_force_backup = false;
1228 /* Backup the ogg packet (likely an header packet) */
1231 void *p_org = p_stream->p_headers;
1232 p_stream->i_headers += p_oggpacket->bytes;
1233 p_stream->p_headers = realloc( p_stream->p_headers, p_stream->i_headers );
1234 if( p_stream->p_headers )
1236 memcpy( (unsigned char *)p_stream->p_headers + p_stream->i_headers - p_oggpacket->bytes,
1237 p_oggpacket->packet, p_oggpacket->bytes );
1241 #warning Memory leak
1242 p_stream->i_headers = 0;
1243 p_stream->p_headers = NULL;
1247 else if( xiph_AppendHeaders( &p_stream->i_headers, &p_stream->p_headers,
1248 p_oggpacket->bytes, p_oggpacket->packet ) )
1250 p_stream->i_headers = 0;
1251 p_stream->p_headers = NULL;
1253 if( p_stream->i_headers > 0 )
1255 if( !p_stream->b_force_backup )
1257 /* Last header received, commit changes */
1258 free( p_stream->fmt.p_extra );
1260 p_stream->fmt.i_extra = p_stream->i_headers;
1261 p_stream->fmt.p_extra = malloc( p_stream->i_headers );
1262 if( p_stream->fmt.p_extra )
1263 memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
1264 p_stream->i_headers );
1266 p_stream->fmt.i_extra = 0;
1268 if( p_stream->i_headers > 0 )
1269 Ogg_ExtractMeta( p_demux, & p_stream->fmt,
1270 p_stream->p_headers, p_stream->i_headers );
1272 /* we're not at BOS anymore for this logical stream */
1273 p_stream->b_initializing = false;
1277 b_selected = false; /* Discard the header packet */
1281 p_stream->b_initializing = false;
1284 /* Convert the granulepos into the next pcr */
1285 Ogg_UpdatePCR( p_demux, p_stream, p_oggpacket );
1289 /* This stream isn't currently selected so we don't need to decode it,
1290 * but we did need to store its pcr as it might be selected later on */
1294 if( !( p_block = block_Alloc( p_oggpacket->bytes ) ) ) return;
1295 p_block->i_pts = p_stream->i_pcr;
1297 DemuxDebug( msg_Dbg(p_demux, "block set from granule %"PRId64" to pts/pcr %"PRId64" skip %d",
1298 p_oggpacket->granulepos, p_stream->i_pcr, p_stream->i_skip_frames); )
1300 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1301 p_block->i_nb_samples = Ogg_OpusPacketDuration( p_oggpacket );
1303 /* may need to preroll after a seek or in case of preskip */
1304 if ( p_stream->i_skip_frames > 0 )
1306 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1308 if( p_stream->i_skip_frames >= p_block->i_nb_samples )
1310 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1311 p_stream->i_skip_frames -= p_block->i_nb_samples;
1312 p_block->i_nb_samples = 0;
1316 p_block->i_nb_samples -= p_stream->i_skip_frames;
1317 p_stream->i_skip_frames = 0;
1322 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1323 p_stream->i_skip_frames--;
1327 /* Conditional block fixes */
1328 if ( p_stream->fmt.i_cat == VIDEO_ES &&
1329 Ogg_IsKeyFrame( p_stream, p_oggpacket ) )
1331 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
1333 else if( p_stream->fmt.i_cat == AUDIO_ES )
1335 /* Blatant abuse of the i_length field. */
1336 p_block->i_length = p_stream->i_end_trim;
1338 else if( p_stream->fmt.i_cat == SPU_ES )
1340 p_block->i_length = 0;
1342 else if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
1344 ogg_int64_t nzdts = Oggseek_GranuleToAbsTimestamp( p_stream, p_oggpacket->granulepos, false );
1345 ogg_int64_t nzpts = Oggseek_GranuleToAbsTimestamp( p_stream, p_oggpacket->granulepos, true );
1346 p_block->i_dts = ( nzdts > VLC_TS_INVALID ) ? VLC_TS_0 + nzdts : nzdts;
1347 p_block->i_pts = ( nzpts > VLC_TS_INVALID ) ? VLC_TS_0 + nzpts : nzpts;
1348 /* granulepos for dirac is possibly broken, this value should be ignored */
1349 if( 0 >= p_oggpacket->granulepos )
1351 p_block->i_pts = VLC_TS_INVALID;
1352 p_block->i_dts = p_stream->i_pcr;
1356 if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
1357 p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
1358 p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
1359 p_stream->fmt.i_codec != VLC_CODEC_VP8 &&
1360 p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
1361 p_stream->fmt.i_codec != VLC_CODEC_TARKIN &&
1362 p_stream->fmt.i_codec != VLC_CODEC_THEORA &&
1363 p_stream->fmt.i_codec != VLC_CODEC_DAALA &&
1364 p_stream->fmt.i_codec != VLC_CODEC_CMML &&
1365 p_stream->fmt.i_codec != VLC_CODEC_DIRAC &&
1366 p_stream->fmt.i_codec != VLC_CODEC_KATE )
1368 if( p_oggpacket->bytes <= 0 )
1370 msg_Dbg( p_demux, "discarding 0 sized packet" );
1371 block_Release( p_block );
1374 /* We remove the header from the packet */
1375 i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
1376 i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
1378 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT)
1380 /* But with subtitles we need to retrieve the duration first */
1381 int i, lenbytes = 0;
1383 if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
1385 for( i = 0, lenbytes = 0; i < i_header_len; i++ )
1387 lenbytes = lenbytes << 8;
1388 lenbytes += *(p_oggpacket->packet + i_header_len - i);
1391 if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
1392 ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
1393 p_oggpacket->packet[i_header_len + 1] != 0 &&
1394 p_oggpacket->packet[i_header_len + 1] != '\n' &&
1395 p_oggpacket->packet[i_header_len + 1] != '\r' ) )
1397 p_block->i_length = (mtime_t)lenbytes * 1000;
1402 if( p_block->i_buffer >= (unsigned int)i_header_len )
1403 p_block->i_buffer -= i_header_len;
1405 p_block->i_buffer = 0;
1409 if( p_stream->fmt.i_codec == VLC_CODEC_TARKIN )
1411 /* FIXME: the biggest hack I've ever done */
1412 msg_Warn( p_demux, "tarkin pts: %"PRId64", granule: %"PRId64,
1413 p_block->i_pts, p_block->i_dts );
1417 memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
1418 p_oggpacket->bytes - i_header_len );
1420 Ogg_SendOrQueueBlocks( p_demux, p_stream, p_block );
1423 static int Ogg_OpusPacketDuration( ogg_packet *p_oggpacket )
1425 return opus_frame_duration(p_oggpacket->packet, p_oggpacket->bytes);
1428 /****************************************************************************
1429 * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
1430 * stream and fill p_ogg.
1431 *****************************************************************************
1432 * The initial page of a logical stream is marked as a 'bos' page.
1433 * Furthermore, the Ogg specification mandates that grouped bitstreams begin
1434 * together and all of the initial pages must appear before any data pages.
1436 * On success this function returns VLC_SUCCESS.
1437 ****************************************************************************/
1438 static int Ogg_FindLogicalStreams( demux_t *p_demux )
1440 demux_sys_t *p_ogg = p_demux->p_sys ;
1441 ogg_packet oggpacket;
1444 p_ogg->i_total_length = stream_Size ( p_demux->s );
1445 msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_length );
1448 while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS )
1451 if( ogg_page_bos( &p_ogg->current_page ) )
1454 /* All is wonderful in our fine fine little world.
1455 * We found the beginning of our first logical stream. */
1456 while( ogg_page_bos( &p_ogg->current_page ) )
1458 logical_stream_t *p_stream;
1460 p_stream = malloc( sizeof(logical_stream_t) );
1461 if( unlikely( !p_stream ) )
1464 TAB_APPEND( p_ogg->i_streams, p_ogg->pp_stream, p_stream );
1466 memset( p_stream, 0, sizeof(logical_stream_t) );
1468 es_format_Init( &p_stream->fmt, 0, 0 );
1469 es_format_Init( &p_stream->fmt_old, 0, 0 );
1470 p_stream->b_initializing = true;
1472 /* Setup the logical stream */
1473 p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page );
1474 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
1476 /* Extract the initial header from the first page and verify
1477 * the codec type of this Ogg bitstream */
1478 if( ogg_stream_pagein( &p_stream->os, &p_ogg->current_page ) < 0 )
1480 /* error. stream version mismatch perhaps */
1481 msg_Err( p_demux, "error reading first page of "
1482 "Ogg bitstream data" );
1483 return VLC_EGENERIC;
1486 /* FIXME: check return value */
1487 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
1489 /* Check for Vorbis header */
1490 if( oggpacket.bytes >= 7 &&
1491 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
1493 if ( Ogg_ReadVorbisHeader( p_stream, &oggpacket ) )
1494 msg_Dbg( p_demux, "found vorbis header" );
1497 msg_Dbg( p_demux, "found invalid vorbis header" );
1498 Ogg_LogicalStreamDelete( p_demux, p_stream );
1502 /* Check for Speex header */
1503 else if( oggpacket.bytes >= 5 &&
1504 ! memcmp( oggpacket.packet, "Speex", 5 ) )
1506 if ( Ogg_ReadSpeexHeader( p_stream, &oggpacket ) )
1507 msg_Dbg( p_demux, "found speex header, channels: %i, "
1508 "rate: %i, bitrate: %i, frames: %i group %i",
1509 p_stream->fmt.audio.i_channels,
1510 (int)p_stream->f_rate, p_stream->fmt.i_bitrate,
1511 p_stream->special.speex.i_framesize,
1512 p_stream->special.speex.i_framesperpacket );
1515 msg_Dbg( p_demux, "found invalid Speex header" );
1516 Ogg_LogicalStreamDelete( p_demux, p_stream );
1520 /* Check for Opus header */
1521 else if( oggpacket.bytes >= 8 &&
1522 ! memcmp( oggpacket.packet, "OpusHead", 8 ) )
1524 Ogg_ReadOpusHeader( p_stream, &oggpacket );
1525 msg_Dbg( p_demux, "found opus header, channels: %i, "
1527 p_stream->fmt.audio.i_channels,
1528 (int)p_stream->i_pre_skip);
1529 p_stream->i_skip_frames = p_stream->i_pre_skip;
1531 /* Check for Flac header (< version 1.1.1) */
1532 else if( oggpacket.bytes >= 4 &&
1533 ! memcmp( oggpacket.packet, "fLaC", 4 ) )
1535 msg_Dbg( p_demux, "found FLAC header" );
1537 /* Grrrr!!!! Did they really have to put all the
1538 * important info in the second header packet!!!
1539 * (STREAMINFO metadata is in the following packet) */
1540 p_stream->b_force_backup = true;
1541 p_stream->fmt.i_cat = AUDIO_ES;
1542 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1544 /* Check for Flac header (>= version 1.1.1) */
1545 else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
1546 ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
1547 ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
1549 int i_packets = ((int)oggpacket.packet[7]) << 8 |
1550 oggpacket.packet[8];
1551 msg_Dbg( p_demux, "found FLAC header version %i.%i "
1552 "(%i header packets)",
1553 oggpacket.packet[5], oggpacket.packet[6],
1556 p_stream->b_force_backup = true;
1558 p_stream->fmt.i_cat = AUDIO_ES;
1559 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1560 oggpacket.packet += 13; oggpacket.bytes -= 13;
1561 if ( !Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket ) )
1563 msg_Dbg( p_demux, "found invalid Flac header" );
1564 Ogg_LogicalStreamDelete( p_demux, p_stream );
1568 /* Check for Theora header */
1569 else if( oggpacket.bytes >= 7 &&
1570 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
1572 if ( Ogg_ReadTheoraHeader( p_stream, &oggpacket ) )
1574 "found theora header, bitrate: %i, rate: %f",
1575 p_stream->fmt.i_bitrate, p_stream->f_rate );
1578 msg_Dbg( p_demux, "found invalid Theora header" );
1579 Ogg_LogicalStreamDelete( p_demux, p_stream );
1583 /* Check for Daala header */
1584 else if( oggpacket.bytes >= 6 &&
1585 ! memcmp( oggpacket.packet, "\x80""daala", 6 ) )
1587 if ( Ogg_ReadDaalaHeader( p_stream, &oggpacket ) )
1589 "found daala header, bitrate: %i, rate: %f",
1590 p_stream->fmt.i_bitrate, p_stream->f_rate );
1593 msg_Dbg( p_demux, "found invalid Daala header" );
1594 Ogg_LogicalStreamDelete( p_demux, p_stream );
1598 /* Check for Dirac header */
1599 else if( ( oggpacket.bytes >= 5 &&
1600 ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) ||
1601 ( oggpacket.bytes >= 9 &&
1602 ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) )
1604 if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) )
1605 msg_Dbg( p_demux, "found dirac header" );
1608 msg_Warn( p_demux, "found dirac header isn't decodable" );
1609 Ogg_LogicalStreamDelete( p_demux, p_stream );
1613 /* Check for Tarkin header */
1614 else if( oggpacket.bytes >= 7 &&
1615 ! memcmp( &oggpacket.packet[1], "tarkin", 6 ) )
1619 msg_Dbg( p_demux, "found tarkin header" );
1620 p_stream->fmt.i_cat = VIDEO_ES;
1621 p_stream->fmt.i_codec = VLC_CODEC_TARKIN;
1623 /* Cheat and get additionnal info ;) */
1624 oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
1625 oggpack_adv( &opb, 88 );
1626 oggpack_adv( &opb, 104 );
1627 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
1628 p_stream->f_rate = 2; /* FIXME */
1630 "found tarkin header, bitrate: %i, rate: %f",
1631 p_stream->fmt.i_bitrate, p_stream->f_rate );
1633 /* Check for VP8 header */
1634 else if( oggpacket.bytes >= 26 &&
1635 ! memcmp( oggpacket.packet, "OVP80", 5 ) )
1637 if ( Ogg_ReadVP8Header( p_demux, p_stream, &oggpacket ) )
1638 msg_Dbg( p_demux, "found VP8 header "
1639 "fps: %f, width:%i; height:%i",
1641 p_stream->fmt.video.i_width,
1642 p_stream->fmt.video.i_height );
1645 msg_Dbg( p_demux, "invalid VP8 header found");
1646 Ogg_LogicalStreamDelete( p_demux, p_stream );
1650 /* Check for Annodex header */
1651 else if( oggpacket.bytes >= 7 &&
1652 ! memcmp( oggpacket.packet, "Annodex", 7 ) )
1654 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1655 /* kill annodex track */
1659 /* Check for Annodex header */
1660 else if( oggpacket.bytes >= 7 &&
1661 ! memcmp( oggpacket.packet, "AnxData", 7 ) )
1663 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1665 /* Check for Kate header */
1666 else if( oggpacket.bytes >= 8 &&
1667 ! memcmp( &oggpacket.packet[1], "kate\0\0\0", 7 ) )
1669 if ( Ogg_ReadKateHeader( p_stream, &oggpacket ) )
1670 msg_Dbg( p_demux, "found kate header" );
1673 msg_Dbg( p_demux, "invalid kate header found");
1674 Ogg_LogicalStreamDelete( p_demux, p_stream );
1678 /* Check for OggDS */
1679 else if( oggpacket.bytes >= 142 &&
1680 !memcmp( &oggpacket.packet[1],
1681 "Direct Show Samples embedded in Ogg", 35 ))
1683 /* Old header type */
1684 p_stream->b_oggds = true;
1685 /* Check for video header (old format) */
1686 if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
1687 oggpacket.bytes >= 184 )
1689 p_stream->fmt.i_cat = VIDEO_ES;
1690 p_stream->fmt.i_codec =
1691 VLC_FOURCC( oggpacket.packet[68],
1692 oggpacket.packet[69],
1693 oggpacket.packet[70],
1694 oggpacket.packet[71] );
1695 msg_Dbg( p_demux, "found video header of type: %.4s",
1696 (char *)&p_stream->fmt.i_codec );
1698 p_stream->fmt.video.i_frame_rate = 10000000;
1699 p_stream->fmt.video.i_frame_rate_base =
1700 GetQWLE((oggpacket.packet+164));
1701 p_stream->fmt.video.i_frame_rate_base =
1702 __MAX( p_stream->fmt.video.i_frame_rate_base, 1 );
1703 p_stream->f_rate = 10000000.0 /
1704 p_stream->fmt.video.i_frame_rate_base;
1705 p_stream->fmt.video.i_bits_per_pixel =
1706 GetWLE((oggpacket.packet+182));
1707 if( !p_stream->fmt.video.i_bits_per_pixel )
1709 p_stream->fmt.video.i_bits_per_pixel = 24;
1710 p_stream->fmt.video.i_width =
1711 GetDWLE((oggpacket.packet+176));
1712 p_stream->fmt.video.i_height =
1713 GetDWLE((oggpacket.packet+180));
1716 "fps: %f, width:%i; height:%i, bitcount:%i",
1718 p_stream->fmt.video.i_width,
1719 p_stream->fmt.video.i_height,
1720 p_stream->fmt.video.i_bits_per_pixel);
1723 /* Check for audio header (old format) */
1724 else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
1727 unsigned int i_format_tag;
1729 p_stream->fmt.i_cat = AUDIO_ES;
1731 i_extra_size = GetWLE((oggpacket.packet+140));
1732 if( i_extra_size > 0 && i_extra_size < oggpacket.bytes - 142 )
1734 p_stream->fmt.i_extra = i_extra_size;
1735 p_stream->fmt.p_extra = malloc( i_extra_size );
1736 if( p_stream->fmt.p_extra )
1737 memcpy( p_stream->fmt.p_extra,
1738 oggpacket.packet + 142, i_extra_size );
1740 p_stream->fmt.i_extra = 0;
1743 i_format_tag = GetWLE((oggpacket.packet+124));
1744 p_stream->fmt.audio.i_channels =
1745 GetWLE((oggpacket.packet+126));
1746 fill_channels_info(&p_stream->fmt.audio);
1747 p_stream->f_rate = p_stream->fmt.audio.i_rate =
1748 GetDWLE((oggpacket.packet+128));
1749 p_stream->fmt.i_bitrate =
1750 GetDWLE((oggpacket.packet+132)) * 8;
1751 p_stream->fmt.audio.i_blockalign =
1752 GetWLE((oggpacket.packet+136));
1753 p_stream->fmt.audio.i_bitspersample =
1754 GetWLE((oggpacket.packet+138));
1756 wf_tag_to_fourcc( i_format_tag,
1757 &p_stream->fmt.i_codec, 0 );
1759 if( p_stream->fmt.i_codec ==
1760 VLC_FOURCC('u','n','d','f') )
1762 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1763 ( i_format_tag >> 8 ) & 0xff,
1764 i_format_tag & 0xff );
1767 msg_Dbg( p_demux, "found audio header of type: %.4s",
1768 (char *)&p_stream->fmt.i_codec );
1769 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1770 "%dbits/sample %dkb/s",
1772 p_stream->fmt.audio.i_channels,
1773 p_stream->fmt.audio.i_rate,
1774 p_stream->fmt.audio.i_bitspersample,
1775 p_stream->fmt.i_bitrate / 1024 );
1776 if ( p_stream->f_rate == 0 )
1778 msg_Dbg( p_demux, "invalid oggds audio header" );
1779 Ogg_LogicalStreamDelete( p_demux, p_stream );
1785 msg_Dbg( p_demux, "stream %d has an old header "
1786 "but is of an unknown type", p_ogg->i_streams-1 );
1791 /* Check for OggDS */
1792 else if( oggpacket.bytes >= 44+1 &&
1793 (*oggpacket.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER )
1795 stream_header_t tmp;
1796 stream_header_t *st = &tmp;
1798 p_stream->b_oggds = true;
1800 memcpy( st->streamtype, &oggpacket.packet[1+0], 8 );
1801 memcpy( st->subtype, &oggpacket.packet[1+8], 4 );
1802 st->size = GetDWLE( &oggpacket.packet[1+12] );
1803 st->time_unit = GetQWLE( &oggpacket.packet[1+16] );
1804 st->samples_per_unit = GetQWLE( &oggpacket.packet[1+24] );
1805 st->default_len = GetDWLE( &oggpacket.packet[1+32] );
1806 st->buffersize = GetDWLE( &oggpacket.packet[1+36] );
1807 st->bits_per_sample = GetWLE( &oggpacket.packet[1+40] ); // (padding 2)
1809 /* Check for video header (new format) */
1810 if( !strncmp( st->streamtype, "video", 5 ) &&
1811 oggpacket.bytes >= 52+1 )
1813 st->sh.video.width = GetDWLE( &oggpacket.packet[1+44] );
1814 st->sh.video.height = GetDWLE( &oggpacket.packet[1+48] );
1816 p_stream->fmt.i_cat = VIDEO_ES;
1818 /* We need to get rid of the header packet */
1819 ogg_stream_packetout( &p_stream->os, &oggpacket );
1821 p_stream->fmt.i_codec =
1822 VLC_FOURCC( st->subtype[0], st->subtype[1],
1823 st->subtype[2], st->subtype[3] );
1824 msg_Dbg( p_demux, "found video header of type: %.4s",
1825 (char *)&p_stream->fmt.i_codec );
1827 p_stream->fmt.video.i_frame_rate = 10000000;
1828 p_stream->fmt.video.i_frame_rate_base = st->time_unit;
1829 if( st->time_unit <= 0 )
1830 st->time_unit = 400000;
1831 p_stream->f_rate = 10000000.0 / st->time_unit;
1832 p_stream->fmt.video.i_bits_per_pixel = st->bits_per_sample;
1833 p_stream->fmt.video.i_width = st->sh.video.width;
1834 p_stream->fmt.video.i_height = st->sh.video.height;
1837 "fps: %f, width:%i; height:%i, bitcount:%i",
1839 p_stream->fmt.video.i_width,
1840 p_stream->fmt.video.i_height,
1841 p_stream->fmt.video.i_bits_per_pixel );
1843 /* Check for audio header (new format) */
1844 else if( !strncmp( st->streamtype, "audio", 5 ) &&
1845 oggpacket.bytes >= 56+1 )
1851 st->sh.audio.channels = GetWLE( &oggpacket.packet[1+44] );
1852 st->sh.audio.blockalign = GetWLE( &oggpacket.packet[1+48] );
1853 st->sh.audio.avgbytespersec = GetDWLE( &oggpacket.packet[1+52] );
1855 p_stream->fmt.i_cat = AUDIO_ES;
1857 /* We need to get rid of the header packet */
1858 ogg_stream_packetout( &p_stream->os, &oggpacket );
1860 i_extra_size = st->size - 56;
1862 if( i_extra_size > 0 &&
1863 i_extra_size < oggpacket.bytes - 1 - 56 )
1865 p_stream->fmt.i_extra = i_extra_size;
1866 p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
1867 if( p_stream->fmt.p_extra )
1868 memcpy( p_stream->fmt.p_extra, oggpacket.packet + 57,
1869 p_stream->fmt.i_extra );
1871 p_stream->fmt.i_extra = 0;
1874 memcpy( p_buffer, st->subtype, 4 );
1876 i_format_tag = strtol(p_buffer,NULL,16);
1877 p_stream->fmt.audio.i_channels = st->sh.audio.channels;
1878 fill_channels_info(&p_stream->fmt.audio);
1879 if( st->time_unit <= 0 )
1880 st->time_unit = 10000000;
1881 p_stream->f_rate = p_stream->fmt.audio.i_rate = st->samples_per_unit * 10000000 / st->time_unit;
1882 p_stream->fmt.i_bitrate = st->sh.audio.avgbytespersec * 8;
1883 p_stream->fmt.audio.i_blockalign = st->sh.audio.blockalign;
1884 p_stream->fmt.audio.i_bitspersample = st->bits_per_sample;
1886 wf_tag_to_fourcc( i_format_tag,
1887 &p_stream->fmt.i_codec, 0 );
1889 if( p_stream->fmt.i_codec ==
1890 VLC_FOURCC('u','n','d','f') )
1892 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1893 ( i_format_tag >> 8 ) & 0xff,
1894 i_format_tag & 0xff );
1897 msg_Dbg( p_demux, "found audio header of type: %.4s",
1898 (char *)&p_stream->fmt.i_codec );
1899 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1900 "%dbits/sample %dkb/s",
1902 p_stream->fmt.audio.i_channels,
1903 p_stream->fmt.audio.i_rate,
1904 p_stream->fmt.audio.i_bitspersample,
1905 p_stream->fmt.i_bitrate / 1024 );
1906 if ( p_stream->f_rate == 0 )
1908 msg_Dbg( p_demux, "invalid oggds audio header" );
1909 Ogg_LogicalStreamDelete( p_demux, p_stream );
1913 /* Check for text (subtitles) header */
1914 else if( !strncmp(st->streamtype, "text", 4) )
1916 /* We need to get rid of the header packet */
1917 ogg_stream_packetout( &p_stream->os, &oggpacket );
1919 msg_Dbg( p_demux, "found text subtitle header" );
1920 p_stream->fmt.i_cat = SPU_ES;
1921 p_stream->fmt.i_codec = VLC_CODEC_SUBT;
1922 p_stream->f_rate = 1000; /* granulepos is in millisec */
1926 msg_Dbg( p_demux, "stream %d has a header marker "
1927 "but is of an unknown type", p_ogg->i_streams-1 );
1932 else if( oggpacket.bytes >= 8 &&
1933 ! memcmp( oggpacket.packet, "fishead\0", 8 ) )
1937 msg_Dbg( p_demux, "stream %d is a skeleton",
1938 p_ogg->i_streams-1 );
1939 Ogg_ReadSkeletonHeader( p_demux, p_stream, &oggpacket );
1943 msg_Dbg( p_demux, "stream %d is of unknown type",
1944 p_ogg->i_streams-1 );
1949 /* we'll need to get all headers */
1950 p_ogg->pp_stream[i_stream]->b_initializing &= p_ogg->pp_stream[i_stream]->b_force_backup;
1952 if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS )
1953 return VLC_EGENERIC;
1956 /* This is the first data page, which means we are now finished
1957 * with the initial pages. We just need to store it in the relevant
1959 for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1961 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
1962 &p_ogg->current_page ) == 0 )
1964 p_ogg->b_page_waiting = true;
1973 return VLC_EGENERIC;
1976 /****************************************************************************
1977 * Ogg_CreateES: Creates all Elementary streams once headers are parsed
1978 ****************************************************************************/
1979 static void Ogg_CreateES( demux_t *p_demux )
1981 demux_sys_t *p_ogg = p_demux->p_sys;
1982 logical_stream_t *p_old_stream = p_ogg->p_old_stream;
1985 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1987 logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
1989 if ( p_stream->p_es == NULL && !p_stream->b_finished )
1991 /* Better be safe than sorry when possible with ogm */
1992 if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
1993 p_stream->fmt.i_codec == VLC_CODEC_A52 )
1994 p_stream->fmt.b_packetized = false;
1996 /* Try first to reuse an old ES */
1998 p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
1999 p_old_stream->fmt.i_codec == p_stream->fmt.i_codec )
2001 msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
2003 p_stream->p_es = p_old_stream->p_es;
2004 p_stream->b_finished = false;
2005 p_stream->b_reinit = false;
2006 p_stream->b_initializing = false;
2007 p_stream->i_pre_skip = 0;
2008 bool b_resetdecoder = Ogg_LogicalStreamResetEsFormat( p_demux, p_stream );
2009 es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
2011 p_old_stream->p_es = NULL;
2012 p_old_stream = NULL;
2013 if ( b_resetdecoder )
2015 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
2016 p_stream->p_es, &p_stream->fmt );
2021 p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
2024 // TODO: something to do here ?
2025 if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
2027 /* Set the CMML stream active */
2028 es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
2033 if( p_ogg->p_old_stream )
2035 if( p_ogg->p_old_stream->p_es )
2036 msg_Dbg( p_demux, "old stream not reused" );
2037 Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
2038 p_ogg->p_old_stream = NULL;
2042 /****************************************************************************
2043 * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
2044 * Elementary streams.
2045 ****************************************************************************/
2046 static int Ogg_BeginningOfStream( demux_t *p_demux )
2048 demux_sys_t *p_ogg = p_demux->p_sys ;
2051 /* Find the logical streams embedded in the physical stream and
2052 * initialize our p_ogg structure. */
2053 if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS )
2055 msg_Warn( p_demux, "couldn't find any ogg logical stream" );
2056 return VLC_EGENERIC;
2059 p_ogg->i_bitrate = 0;
2061 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
2063 logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
2065 p_stream->p_es = NULL;
2067 /* initialise kframe index */
2070 if ( p_stream->fmt.i_bitrate == 0 &&
2071 ( p_stream->fmt.i_cat == VIDEO_ES ||
2072 p_stream->fmt.i_cat == AUDIO_ES ) )
2073 p_ogg->b_partial_bitrate = true;
2075 p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
2077 p_stream->i_pcr = p_stream->i_previous_pcr = VLC_TS_UNKNOWN;
2078 p_stream->i_previous_granulepos = -1;
2079 p_stream->b_reinit = false;
2082 /* get total frame count for video stream; we will need this for seeking */
2083 p_ogg->i_total_frames = 0;
2088 /****************************************************************************
2089 * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
2090 ****************************************************************************/
2091 static void Ogg_EndOfStream( demux_t *p_demux )
2093 demux_sys_t *p_ogg = p_demux->p_sys ;
2096 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
2097 Ogg_LogicalStreamDelete( p_demux, p_ogg->pp_stream[i_stream] );
2098 free( p_ogg->pp_stream );
2101 p_ogg->i_bitrate = 0;
2102 p_ogg->i_streams = 0;
2103 p_ogg->pp_stream = NULL;
2104 p_ogg->skeleton.major = 0;
2105 p_ogg->skeleton.minor = 0;
2106 p_ogg->b_preparsing_done = false;
2107 p_ogg->b_es_created = false;
2108 p_ogg->i_nzpcr_offset = (p_ogg->i_pcr >= VLC_TS_INVALID) ?
2109 p_ogg->i_pcr - VLC_TS_0 : 0;
2113 vlc_meta_Delete( p_ogg->p_meta );
2114 p_ogg->p_meta = NULL;
2116 for ( int i=0; i < p_ogg->i_seekpoints; i++ )
2118 if ( p_ogg->pp_seekpoints[i] )
2119 vlc_seekpoint_Delete( p_ogg->pp_seekpoints[i] );
2121 TAB_CLEAN( p_ogg->i_seekpoints, p_ogg->pp_seekpoints );
2122 p_ogg->i_seekpoints = 0;
2125 static void Ogg_CleanSpecificData( logical_stream_t *p_stream )
2127 #ifdef HAVE_LIBVORBIS
2128 if ( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2130 FREENULL( p_stream->special.vorbis.p_info );
2131 FREENULL( p_stream->special.vorbis.p_comment );
2132 p_stream->special.vorbis.i_headers_flags = 0;
2135 VLC_UNUSED( p_stream );
2140 * This function delete and release all data associated to a logical_stream_t
2142 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream )
2144 if( p_stream->p_es )
2145 es_out_Del( p_demux->out, p_stream->p_es );
2147 ogg_stream_clear( &p_stream->os );
2148 free( p_stream->p_headers );
2150 Ogg_CleanSpecificData( p_stream );
2152 es_format_Clean( &p_stream->fmt_old );
2153 es_format_Clean( &p_stream->fmt );
2155 if ( p_stream->idx != NULL)
2157 oggseek_index_entries_free( p_stream->idx );
2160 Ogg_FreeSkeleton( p_stream->p_skel );
2161 p_stream->p_skel = NULL;
2162 if ( p_demux->p_sys->p_skelstream == p_stream )
2163 p_demux->p_sys->p_skelstream = NULL;
2165 /* Shouldn't happen */
2166 if ( unlikely( p_stream->p_preparse_block ) )
2168 block_ChainRelease( p_stream->p_preparse_block );
2169 p_stream->p_preparse_block = NULL;
2171 free( p_stream->p_prepcr_blocks );
2176 * This function check if a we need to reset a decoder in case we are
2179 static bool Ogg_IsVorbisFormatCompatible( const es_format_t *p_new, const es_format_t *p_old )
2181 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
2182 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2183 unsigned i_new_count;
2184 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
2187 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
2188 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2189 unsigned i_old_count;
2190 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
2193 bool b_match = i_new_count == i_old_count;
2194 for( unsigned i = 0; i < i_new_count && b_match; i++ )
2196 /* Ignore vorbis comment */
2199 if( pi_new_size[i] != pi_old_size[i] ||
2200 memcmp( pp_new_data[i], pp_old_data[i], pi_new_size[i] ) )
2207 static bool Ogg_IsOpusFormatCompatible( const es_format_t *p_new,
2208 const es_format_t *p_old )
2210 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
2211 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2212 unsigned i_new_count;
2213 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
2215 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
2216 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2217 unsigned i_old_count;
2218 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
2220 bool b_match = false;
2221 if( i_new_count == i_old_count && i_new_count > 0 )
2223 static const unsigned char default_map[2] = { 0, 1 };
2224 unsigned char *p_old_head;
2225 unsigned char *p_new_head;
2226 const unsigned char *p_old_map;
2227 const unsigned char *p_new_map;
2228 int i_old_channel_count;
2229 int i_new_channel_count;
2230 int i_old_stream_count;
2231 int i_new_stream_count;
2232 int i_old_coupled_count;
2233 int i_new_coupled_count;
2234 p_old_head = (unsigned char *)pp_old_data[0];
2235 i_old_channel_count = i_old_stream_count = i_old_coupled_count = 0;
2236 p_old_map = default_map;
2237 if( pi_old_size[0] >= 19 && p_old_head[8] <= 15 )
2239 i_old_channel_count = p_old_head[9];
2240 switch( p_old_head[18] )
2243 i_old_stream_count = 1;
2244 i_old_coupled_count = i_old_channel_count - 1;
2247 if( pi_old_size[0] >= 21U + i_old_channel_count )
2249 i_old_stream_count = p_old_head[19];
2250 i_old_coupled_count = p_old_head[20];
2251 p_old_map = p_old_head + 21;
2256 p_new_head = (unsigned char *)pp_new_data[0];
2257 i_new_channel_count = i_new_stream_count = i_new_coupled_count = 0;
2258 p_new_map = default_map;
2259 if( pi_new_size[0] >= 19 && p_new_head[8] <= 15 )
2261 i_new_channel_count = p_new_head[9];
2262 switch( p_new_head[18] )
2265 i_new_stream_count = 1;
2266 i_new_coupled_count = i_new_channel_count - 1;
2269 if( pi_new_size[0] >= 21U + i_new_channel_count )
2271 i_new_stream_count = p_new_head[19];
2272 i_new_coupled_count = p_new_head[20];
2273 p_new_map = p_new_head+21;
2278 b_match = i_old_channel_count == i_new_channel_count &&
2279 i_old_stream_count == i_new_stream_count &&
2280 i_old_coupled_count == i_new_coupled_count &&
2281 memcmp(p_old_map, p_new_map,
2282 i_new_channel_count*sizeof(*p_new_map)) == 0;
2288 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream )
2290 bool b_compatible = false;
2291 if( !p_stream->fmt_old.i_cat || !p_stream->fmt_old.i_codec )
2294 /* Only Vorbis and Opus are supported. */
2295 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2296 b_compatible = Ogg_IsVorbisFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2297 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
2298 b_compatible = Ogg_IsOpusFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2301 msg_Warn( p_demux, "cannot reuse old stream, resetting the decoder" );
2303 return !b_compatible;
2306 static void Ogg_ExtractComments( demux_t *p_demux, es_format_t *p_fmt,
2307 const void *p_headers, unsigned i_headers )
2309 demux_sys_t *p_ogg = p_demux->p_sys;
2310 int i_cover_score = 0;
2311 int i_cover_idx = 0;
2312 float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
2313 float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
2314 for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
2316 pf_replay_gain[i] = 0;
2317 pf_replay_peak[i] = 0;
2319 vorbis_ParseComment( p_fmt, &p_ogg->p_meta, p_headers, i_headers,
2320 &p_ogg->i_attachments, &p_ogg->attachments,
2321 &i_cover_score, &i_cover_idx,
2322 &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
2323 &pf_replay_gain, &pf_replay_peak );
2324 if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
2327 snprintf( psz_url, sizeof(psz_url), "attachment://%s",
2328 p_ogg->attachments[i_cover_idx]->psz_name );
2329 vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
2332 for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
2334 if ( pf_replay_gain[i] != 0 )
2336 p_fmt->audio_replay_gain.pb_gain[i] = true;
2337 p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
2338 msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
2340 if ( pf_replay_peak[i] != 0 )
2342 p_fmt->audio_replay_gain.pb_peak[i] = true;
2343 p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
2344 msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
2348 if( p_ogg->i_seekpoints > 1 )
2350 p_demux->info.i_update |= INPUT_UPDATE_TITLE_LIST;
2354 static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
2355 const void *p_headers, unsigned i_headers, unsigned i_skip )
2357 unsigned pi_size[XIPH_MAX_HEADER_COUNT];
2358 void *pp_data[XIPH_MAX_HEADER_COUNT];
2361 if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
2363 /* TODO how to handle multiple comments properly ? */
2364 if( i_count >= 2 && pi_size[1] > i_skip )
2366 Ogg_ExtractComments( p_demux, p_fmt, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip );
2370 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers )
2372 demux_sys_t *p_ogg = p_demux->p_sys;
2374 switch( p_fmt->i_codec )
2376 /* 3 headers with the 2° one being the comments */
2377 case VLC_CODEC_VORBIS:
2378 case VLC_CODEC_THEORA:
2379 case VLC_CODEC_DAALA:
2380 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+6 );
2382 case VLC_CODEC_OPUS:
2383 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 8 );
2385 case VLC_CODEC_SPEEX:
2386 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
2389 Ogg_ExtractComments( p_demux, p_fmt, p_headers, i_headers );
2391 /* N headers with the 2° one being the comments */
2392 case VLC_CODEC_KATE:
2393 /* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
2394 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+7+1 );
2398 case VLC_CODEC_FLAC:
2399 msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&p_fmt->i_codec );
2403 case VLC_CODEC_CMML: /* CMML is XML text, doesn't have Vorbis comments */
2404 case VLC_CODEC_DIRAC:
2409 p_demux->info.i_update |= INPUT_UPDATE_META;
2412 static bool Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
2413 ogg_packet *p_oggpacket )
2416 unsigned int i_fps_numerator;
2417 unsigned int i_fps_denominator;
2418 int i_keyframe_frequency_force;
2424 p_stream->fmt.i_cat = VIDEO_ES;
2425 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2427 /* Signal that we want to keep a backup of the theora
2428 * stream headers. They will be used when switching between
2430 p_stream->b_force_backup = true;
2432 /* Cheat and get additionnal info ;) */
2433 bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
2434 bs_skip( &bitstream, 56 );
2436 i_major = bs_read( &bitstream, 8 ); /* major version num */
2437 i_minor = bs_read( &bitstream, 8 ); /* minor version num */
2438 i_subminor = bs_read( &bitstream, 8 ); /* subminor version num */
2440 bs_read( &bitstream, 16 ) /*<< 4*/; /* width */
2441 bs_read( &bitstream, 16 ) /*<< 4*/; /* height */
2442 bs_read( &bitstream, 24 ); /* frame width */
2443 bs_read( &bitstream, 24 ); /* frame height */
2444 bs_read( &bitstream, 8 ); /* x offset */
2445 bs_read( &bitstream, 8 ); /* y offset */
2447 i_fps_numerator = bs_read( &bitstream, 32 );
2448 i_fps_denominator = bs_read( &bitstream, 32 );
2449 i_fps_denominator = __MAX( i_fps_denominator, 1 );
2450 bs_read( &bitstream, 24 ); /* aspect_numerator */
2451 bs_read( &bitstream, 24 ); /* aspect_denominator */
2453 p_stream->fmt.video.i_frame_rate = i_fps_numerator;
2454 p_stream->fmt.video.i_frame_rate_base = i_fps_denominator;
2456 bs_read( &bitstream, 8 ); /* colorspace */
2457 p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
2458 bs_read( &bitstream, 6 ); /* quality */
2460 i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 );
2462 /* granule_shift = i_log( frequency_force -1 ) */
2463 p_stream->i_granule_shift = 0;
2464 i_keyframe_frequency_force--;
2465 while( i_keyframe_frequency_force )
2467 p_stream->i_granule_shift++;
2468 i_keyframe_frequency_force >>= 1;
2471 i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2472 p_stream->i_keyframe_offset = 0;
2473 p_stream->f_rate = ((double)i_fps_numerator) / i_fps_denominator;
2474 if ( p_stream->f_rate == 0 ) return false;
2476 if ( i_version >= 3002001 )
2478 p_stream->i_keyframe_offset = 1;
2483 static bool Ogg_ReadDaalaHeader( logical_stream_t *p_stream,
2484 ogg_packet *p_oggpacket )
2487 uint32_t i_timebase_numerator;
2488 uint32_t i_timebase_denominator;
2489 int i_keyframe_frequency_force;
2495 p_stream->fmt.i_cat = VIDEO_ES;
2496 p_stream->fmt.i_codec = VLC_CODEC_DAALA;
2498 /* Signal that we want to keep a backup of the daala
2499 * stream headers. They will be used when switching between
2501 p_stream->b_force_backup = true;
2503 /* Cheat and get additionnal info ;) */
2504 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes );
2505 oggpack_adv( &opb, 48 );
2507 i_major = oggpack_read( &opb, 8 ); /* major version num */
2508 i_minor = oggpack_read( &opb, 8 ); /* minor version num */
2509 i_subminor = oggpack_read( &opb, 8 ); /* subminor version num */
2511 oggpack_adv( &opb, 32 ); /* width */
2512 oggpack_adv( &opb, 32 ); /* height */
2514 oggpack_adv( &opb, 32 ); /* aspect numerator */
2515 oggpack_adv( &opb, 32 ); /* aspect denominator */
2516 i_timebase_numerator = oggpack_read( &opb, 32 );
2518 i_timebase_denominator = oggpack_read( &opb, 32 );
2519 i_timebase_denominator = __MAX( i_timebase_denominator, 1 );
2521 p_stream->fmt.video.i_frame_rate = i_timebase_numerator;
2522 p_stream->fmt.video.i_frame_rate_base = i_timebase_denominator;
2524 oggpack_adv( &opb, 32 ); /* frame duration */
2526 i_keyframe_frequency_force = 1 << oggpack_read( &opb, 8 );
2528 /* granule_shift = i_log( frequency_force -1 ) */
2529 p_stream->i_granule_shift = 0;
2530 i_keyframe_frequency_force--;
2531 while( i_keyframe_frequency_force )
2533 p_stream->i_granule_shift++;
2534 i_keyframe_frequency_force >>= 1;
2537 i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2538 p_stream->i_keyframe_offset = 0;
2539 p_stream->f_rate = ((double)i_timebase_numerator) / i_timebase_denominator;
2540 if ( p_stream->f_rate == 0 ) return false;
2545 static bool Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
2546 ogg_packet *p_oggpacket )
2550 p_stream->fmt.i_cat = AUDIO_ES;
2551 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2553 /* Signal that we want to keep a backup of the vorbis
2554 * stream headers. They will be used when switching between
2556 p_stream->b_force_backup = true;
2558 /* Cheat and get additionnal info ;) */
2559 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2560 oggpack_adv( &opb, 88 );
2561 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2562 fill_channels_info(&p_stream->fmt.audio);
2563 p_stream->f_rate = p_stream->fmt.audio.i_rate =
2564 oggpack_read( &opb, 32 );
2565 oggpack_adv( &opb, 32 );
2566 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); /* is signed 32 */
2567 if( p_stream->fmt.i_bitrate > INT32_MAX ) p_stream->fmt.i_bitrate = 0;
2568 if ( p_stream->f_rate == 0 ) return false;
2571 #ifdef HAVE_LIBVORBIS
2572 static void Ogg_DecodeVorbisHeader( logical_stream_t *p_stream,
2573 ogg_packet *p_oggpacket, int i_number )
2577 case VORBIS_HEADER_IDENTIFICATION:
2578 p_stream->special.vorbis.p_info = malloc( sizeof(vorbis_info) );
2579 p_stream->special.vorbis.p_comment = malloc( sizeof(vorbis_comment) );
2580 if ( !p_stream->special.vorbis.p_info || !p_stream->special.vorbis.p_comment )
2582 FREENULL( p_stream->special.vorbis.p_info );
2583 FREENULL( p_stream->special.vorbis.p_comment );
2586 vorbis_info_init( p_stream->special.vorbis.p_info );
2587 vorbis_comment_init( p_stream->special.vorbis.p_comment );
2590 case VORBIS_HEADER_COMMENT:
2591 case VORBIS_HEADER_SETUP:
2592 if ( !p_stream->special.vorbis.p_info ||
2593 vorbis_synthesis_headerin(
2594 p_stream->special.vorbis.p_info,
2595 p_stream->special.vorbis.p_comment, p_oggpacket ) )
2598 p_stream->special.vorbis.i_headers_flags |= VORBIS_HEADER_TO_FLAG(i_number);
2607 static bool Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
2608 ogg_packet *p_oggpacket )
2612 p_stream->fmt.i_cat = AUDIO_ES;
2613 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2615 /* Signal that we want to keep a backup of the speex
2616 * stream headers. They will be used when switching between
2618 p_stream->b_force_backup = true;
2620 /* Cheat and get additionnal info ;) */
2621 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2622 oggpack_adv( &opb, 224 );
2623 oggpack_adv( &opb, 32 ); /* speex_version_id */
2624 oggpack_adv( &opb, 32 ); /* header_size */
2625 p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
2626 if ( p_stream->f_rate == 0 ) return false;
2627 oggpack_adv( &opb, 32 ); /* mode */
2628 oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
2629 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
2630 fill_channels_info(&p_stream->fmt.audio);
2631 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2632 p_stream->special.speex.i_framesize =
2633 oggpack_read( &opb, 32 ); /* frame_size */
2634 oggpack_adv( &opb, 32 ); /* vbr */
2635 p_stream->special.speex.i_framesperpacket =
2636 oggpack_read( &opb, 32 ); /* frames_per_packet */
2637 p_stream->i_extra_headers_packets = oggpack_read( &opb, 32 ); /* extra_headers */
2641 static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
2642 ogg_packet *p_oggpacket )
2646 p_stream->fmt.i_cat = AUDIO_ES;
2647 p_stream->fmt.i_codec = VLC_CODEC_OPUS;
2649 /* Signal that we want to keep a backup of the opus
2650 * stream headers. They will be used when switching between
2652 p_stream->b_force_backup = true;
2654 /* All OggOpus streams are timestamped at 48kHz and
2655 * can be played at 48kHz. */
2656 p_stream->f_rate = p_stream->fmt.audio.i_rate = 48000;
2657 p_stream->fmt.i_bitrate = 0;
2659 /* Cheat and get additional info ;) */
2660 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2661 oggpack_adv( &opb, 64 );
2662 oggpack_adv( &opb, 8 ); /* version_id */
2663 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2664 fill_channels_info(&p_stream->fmt.audio);
2665 p_stream->i_pre_skip = oggpack_read( &opb, 16 );
2666 /* For Opus, trash the first 80 ms of decoded output as
2667 well, to avoid blowing out speakers if we get unlucky.
2668 Opus predicts content from prior frames, which can go
2669 badly if we seek right where the stream goes from very
2670 quiet to very loud. It will converge after a bit. */
2671 p_stream->i_pre_skip = __MAX( 80*48, p_stream->i_pre_skip );
2674 static bool Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
2675 ogg_packet *p_oggpacket )
2677 /* Parse the STREAMINFO metadata */
2680 bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
2683 if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) != 0 )
2685 msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
2689 if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
2692 p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
2693 p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
2694 fill_channels_info(&p_stream->fmt.audio);
2696 msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
2697 p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
2698 if ( p_stream->f_rate == 0 ) return false;
2702 msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
2705 /* Fake this as the last metadata block */
2706 *((uint8_t*)p_oggpacket->packet) |= 0x80;
2710 static bool Ogg_ReadKateHeader( logical_stream_t *p_stream,
2711 ogg_packet *p_oggpacket )
2719 p_stream->fmt.i_cat = SPU_ES;
2720 p_stream->fmt.i_codec = VLC_CODEC_KATE;
2722 /* Signal that we want to keep a backup of the kate
2723 * stream headers. They will be used when switching between
2725 p_stream->b_force_backup = true;
2727 /* Cheat and get additionnal info ;) */
2728 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2729 oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */
2730 p_stream->special.kate.i_num_headers = oggpack_read( &opb, 8 );
2731 oggpack_adv( &opb, 3*8 );
2732 p_stream->i_granule_shift = oggpack_read( &opb, 8 );
2733 oggpack_adv( &opb, 8*8 ); /* reserved */
2734 gnum = oggpack_read( &opb, 32 );
2735 gden = oggpack_read( &opb, 32 );
2736 gden = __MAX( gden, 1 );
2737 p_stream->f_rate = (double)gnum/gden;
2738 if ( p_stream->f_rate == 0 ) return false;
2740 p_stream->fmt.psz_language = malloc(16);
2741 if( p_stream->fmt.psz_language )
2743 for( n = 0; n < 16; n++ )
2744 p_stream->fmt.psz_language[n] = oggpack_read(&opb,8);
2745 p_stream->fmt.psz_language[15] = 0; /* just in case */
2749 for( n = 0; n < 16; n++ )
2750 oggpack_read(&opb,8);
2752 p_stream->fmt.psz_description = malloc(16);
2753 if( p_stream->fmt.psz_description )
2755 for( n = 0; n < 16; n++ )
2756 p_stream->fmt.psz_description[n] = oggpack_read(&opb,8);
2757 p_stream->fmt.psz_description[15] = 0; /* just in case */
2759 /* Now find a localized user readable description for this category */
2760 psz_desc = strdup(FindKateCategoryName(p_stream->fmt.psz_description));
2763 free( p_stream->fmt.psz_description );
2764 p_stream->fmt.psz_description = psz_desc;
2769 for( n = 0; n < 16; n++ )
2770 oggpack_read(&opb,8);
2776 static bool Ogg_ReadVP8Header( demux_t *p_demux, logical_stream_t *p_stream,
2777 ogg_packet *p_oggpacket )
2779 switch( p_oggpacket->packet[5] )
2783 /* Mapping version */
2784 if ( p_oggpacket->packet[6] != 0x01 || p_oggpacket->packet[7] != 0x00 )
2786 p_stream->fmt.i_cat = VIDEO_ES;
2787 p_stream->fmt.i_codec = VLC_CODEC_VP8;
2788 p_stream->i_granule_shift = 32;
2789 p_stream->fmt.video.i_width = GetWBE( &p_oggpacket->packet[8] );
2790 p_stream->fmt.video.i_height = GetWBE( &p_oggpacket->packet[10] );
2791 p_stream->fmt.video.i_sar_num = GetDWBE( &p_oggpacket->packet[12 - 1] ) & 0x0FFF;
2792 p_stream->fmt.video.i_sar_den = GetDWBE( &p_oggpacket->packet[15 - 1] ) & 0x0FFF;
2793 p_stream->fmt.video.i_frame_rate = GetDWBE( &p_oggpacket->packet[18] );
2794 p_stream->fmt.video.i_frame_rate_base = GetDWBE( &p_oggpacket->packet[22] );
2795 p_stream->fmt.video.i_frame_rate_base =
2796 __MAX( p_stream->fmt.video.i_frame_rate_base, 1 );
2797 p_stream->f_rate = (double) p_stream->fmt.video.i_frame_rate / p_stream->fmt.video.i_frame_rate_base;
2798 if ( p_stream->f_rate == 0 ) return false;
2802 Ogg_ExtractMeta( p_demux, & p_stream->fmt,
2803 p_oggpacket->packet + 7, p_oggpacket->bytes - 7 );
2810 static void Ogg_ApplyContentType( logical_stream_t *p_stream, const char* psz_value,
2811 bool *b_force_backup, bool *b_packet_out )
2813 if( !strncmp(psz_value, "audio/x-wav", 11) )
2815 /* n.b. WAVs are unsupported right now */
2816 p_stream->fmt.i_cat = UNKNOWN_ES;
2817 free( p_stream->fmt.psz_description );
2818 p_stream->fmt.psz_description = strdup("WAV Audio (Unsupported)");
2820 else if( !strncmp(psz_value, "audio/x-vorbis", 14) ||
2821 !strncmp(psz_value, "audio/vorbis", 12) )
2823 p_stream->fmt.i_cat = AUDIO_ES;
2824 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2826 *b_force_backup = true;
2828 else if( !strncmp(psz_value, "audio/x-speex", 13) ||
2829 !strncmp(psz_value, "audio/speex", 11) )
2831 p_stream->fmt.i_cat = AUDIO_ES;
2832 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2834 *b_force_backup = true;
2836 else if( !strncmp(psz_value, "audio/flac", 10) )
2838 p_stream->fmt.i_cat = AUDIO_ES;
2839 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
2841 *b_force_backup = true;
2843 else if( !strncmp(psz_value, "video/x-theora", 14) ||
2844 !strncmp(psz_value, "video/theora", 12) )
2846 p_stream->fmt.i_cat = VIDEO_ES;
2847 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2849 *b_force_backup = true;
2851 else if( !strncmp(psz_value, "video/x-daala", 13) ||
2852 !strncmp(psz_value, "video/daala", 11) )
2854 p_stream->fmt.i_cat = VIDEO_ES;
2855 p_stream->fmt.i_codec = VLC_CODEC_DAALA;
2857 *b_force_backup = true;
2859 else if( !strncmp(psz_value, "video/x-xvid", 12) )
2861 p_stream->fmt.i_cat = VIDEO_ES;
2862 p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' );
2864 *b_force_backup = true;
2866 else if( !strncmp(psz_value, "video/mpeg", 10) )
2868 /* n.b. MPEG streams are unsupported right now */
2869 p_stream->fmt.i_cat = VIDEO_ES;
2870 p_stream->fmt.i_codec = VLC_CODEC_MPGV;
2872 else if( !strncmp(psz_value, "text/x-cmml", 11) ||
2873 !strncmp(psz_value, "text/cmml", 9) )
2875 p_stream->fmt.i_cat = SPU_ES;
2876 p_stream->fmt.i_codec = VLC_CODEC_CMML;
2877 *b_packet_out = true;
2879 else if( !strncmp(psz_value, "application/kate", 16) )
2882 p_stream->fmt.i_cat = UNKNOWN_ES;
2883 free( p_stream->fmt.psz_description );
2884 p_stream->fmt.psz_description = strdup("OGG Kate Overlay (Unsupported)");
2886 else if( !strncmp(psz_value, "video/x-vp8", 11) )
2888 p_stream->fmt.i_cat = VIDEO_ES;
2889 p_stream->fmt.i_codec = VLC_CODEC_VP8;
2893 static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
2894 logical_stream_t *p_stream,
2895 ogg_packet *p_oggpacket )
2897 if( p_oggpacket->bytes >= 28 &&
2898 !memcmp( p_oggpacket->packet, "Annodex", 7 ) )
2902 uint16_t major_version;
2903 uint16_t minor_version;
2904 uint64_t timebase_numerator;
2905 uint64_t timebase_denominator;
2907 Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
2909 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2910 oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
2911 major_version = oggpack_read( &opb, 2*8 ); /* major version */
2912 minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
2913 timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
2914 timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
2916 msg_Dbg( p_demux, "Annodex info: version %"PRIu16".%"PRIu16" "
2917 "Timebase %"PRId64" / %"PRId64,
2918 major_version, minor_version,
2919 timebase_numerator, timebase_denominator );
2921 else if( p_oggpacket->bytes >= 42 &&
2922 !memcmp( p_oggpacket->packet, "AnxData", 7 ) )
2924 uint64_t granule_rate_numerator;
2925 uint64_t granule_rate_denominator;
2926 char content_type_string[1024];
2928 /* Read in Annodex header fields */
2930 granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
2931 granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
2932 p_stream->i_secondary_header_packets =
2933 GetDWLE( &p_oggpacket->packet[24] );
2935 /* we are guaranteed that the first header field will be
2936 * the content-type (by the Annodex standard) */
2937 content_type_string[0] = '\0';
2938 if( !strncasecmp( (char*)(&p_oggpacket->packet[28]), "Content-Type: ", 14 ) )
2940 uint8_t *p = memchr( &p_oggpacket->packet[42], '\r',
2941 p_oggpacket->bytes - 1 );
2942 if( p && p[0] == '\r' && p[1] == '\n' )
2943 sscanf( (char*)(&p_oggpacket->packet[42]), "%1023s\r\n",
2944 content_type_string );
2947 msg_Dbg( p_demux, "AnxData packet info: %"PRId64" / %"PRId64", %d, ``%s''",
2948 granule_rate_numerator, granule_rate_denominator,
2949 p_stream->i_secondary_header_packets, content_type_string );
2951 p_stream->f_rate = (float) granule_rate_numerator /
2952 (float) granule_rate_denominator;
2954 /* What type of file do we have?
2955 * strcmp is safe to use here because we've extracted
2956 * content_type_string from the stream manually */
2957 bool b_dopacketout = false;
2958 Ogg_ApplyContentType( p_stream, content_type_string,
2959 &p_stream->b_force_backup, &b_dopacketout );
2960 if ( b_dopacketout ) ogg_stream_packetout( &p_stream->os, p_oggpacket );
2964 static void Ogg_ReadSkeletonHeader( demux_t *p_demux, logical_stream_t *p_stream,
2965 ogg_packet *p_oggpacket )
2967 p_demux->p_sys->p_skelstream = p_stream;
2968 /* There can be only 1 skeleton for streams */
2969 p_demux->p_sys->skeleton.major = GetWLE( &p_oggpacket->packet[8] );
2970 p_demux->p_sys->skeleton.minor = GetWLE( &p_oggpacket->packet[10] );
2971 if ( asprintf( & p_stream->fmt.psz_description,
2972 "OGG Skeleton version %" PRIu16 ".%" PRIu16,
2973 p_demux->p_sys->skeleton.major,
2974 p_demux->p_sys->skeleton.minor ) < 0 )
2975 p_stream->fmt.psz_description = NULL;
2978 static void Ogg_ReadSkeletonBones( demux_t *p_demux, ogg_packet *p_oggpacket )
2980 if ( p_demux->p_sys->skeleton.major < 3 || p_oggpacket->bytes < 52 ) return;
2982 /* Find the matching stream for this skeleton data */
2983 ogg_int32_t i_serialno = GetDWLE( &p_oggpacket->packet[12] );
2984 logical_stream_t *p_target_stream = NULL;
2985 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
2987 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
2989 p_target_stream = p_demux->p_sys->pp_stream[i];
2993 if ( !p_target_stream ) return;
2995 ogg_skeleton_t *p_skel = p_target_stream->p_skel;
2998 p_skel = malloc( sizeof( ogg_skeleton_t ) );
2999 if ( !p_skel ) return;
3000 TAB_INIT( p_skel->i_messages, p_skel->ppsz_messages );
3001 p_skel->p_index = NULL;
3002 p_target_stream->p_skel = p_skel;
3005 const unsigned char *p_messages = p_oggpacket->packet + 8 + GetDWLE( &p_oggpacket->packet[8] );
3006 const unsigned char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
3007 const unsigned char *p = p_messages;
3008 while ( p <= p_boundary - 1 && p > p_oggpacket->packet )
3010 if ( *p == 0x0D && *(p+1) == 0x0A )
3012 char *psz_message = strndup( (const char *) p_messages,
3016 msg_Dbg( p_demux, "stream %" PRId32 " [%s]", i_serialno, psz_message );
3017 TAB_APPEND( p_skel->i_messages, p_skel->ppsz_messages, psz_message );
3019 if ( p < p_boundary - 1 ) p_messages = p + 2;
3026 /* Unpacks the 7bit variable encoding used in skeleton indexes */
3027 unsigned const char * Read7BitsVariableLE( unsigned const char *p_begin,
3028 unsigned const char *p_end,
3029 uint64_t *pi_value )
3035 while ( p_begin < p_end )
3037 i_read = *p_begin & 0x7F; /* High bit is start of integer */
3038 *pi_value = *pi_value | ( i_read << i_shift );
3040 if ( (*p_begin++ & 0x80) == 0x80 ) break; /* see prev */
3043 *pi_value = GetQWLE( pi_value );
3047 static void Ogg_ReadSkeletonIndex( demux_t *p_demux, ogg_packet *p_oggpacket )
3049 if ( p_demux->p_sys->skeleton.major < 4
3050 || p_oggpacket->bytes < 44 /* Need at least 1 index value (42+1+1) */
3053 /* Find the matching stream for this skeleton data */
3054 int32_t i_serialno = GetDWLE( &p_oggpacket->packet[6] );
3055 logical_stream_t *p_stream = NULL;
3056 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
3058 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
3060 p_stream = p_demux->p_sys->pp_stream[i];
3064 if ( !p_stream || !p_stream->p_skel ) return;
3065 uint64_t i_keypoints = GetQWLE( &p_oggpacket->packet[10] );
3066 msg_Dbg( p_demux, "%" PRIi64 " index data for %" PRIi32, i_keypoints, i_serialno );
3067 if ( !i_keypoints ) return;
3069 p_stream->p_skel->i_indexstampden = GetQWLE( &p_oggpacket->packet[18] );
3070 p_stream->p_skel->i_indexfirstnum = GetQWLE( &p_oggpacket->packet[24] );
3071 p_stream->p_skel->i_indexlastnum = GetQWLE( &p_oggpacket->packet[32] );
3072 unsigned const char *p_fwdbyte = &p_oggpacket->packet[42];
3073 unsigned const char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
3074 uint64_t i_offset = 0;
3075 uint64_t i_time = 0;
3076 uint64_t i_keypoints_found = 0;
3078 while( p_fwdbyte < p_boundary && i_keypoints_found < i_keypoints )
3081 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
3083 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
3084 i_time += i_val * p_stream->p_skel->i_indexstampden;
3085 i_keypoints_found++;
3088 if ( i_keypoints_found != i_keypoints )
3090 msg_Warn( p_demux, "Invalid Index: missing entries" );
3094 p_stream->p_skel->p_index = malloc( p_oggpacket->bytes - 42 );
3095 if ( !p_stream->p_skel->p_index ) return;
3096 memcpy( p_stream->p_skel->p_index, &p_oggpacket->packet[42],
3097 p_oggpacket->bytes - 42 );
3098 p_stream->p_skel->i_index = i_keypoints_found;
3099 p_stream->p_skel->i_index_size = p_oggpacket->bytes - 42;
3102 static void Ogg_FreeSkeleton( ogg_skeleton_t *p_skel )
3104 if ( !p_skel ) return;
3105 for ( int i=0; i< p_skel->i_messages; i++ )
3106 free( p_skel->ppsz_messages[i] );
3107 TAB_CLEAN( p_skel->i_messages, p_skel->ppsz_messages );
3108 free( p_skel->p_index );
3112 static void Ogg_ApplySkeleton( logical_stream_t *p_stream )
3114 if ( !p_stream->p_skel ) return;
3115 for ( int i=0; i< p_stream->p_skel->i_messages; i++ )
3117 const char *psz_message = p_stream->p_skel->ppsz_messages[i];
3118 if ( ! strncmp( "Name: ", psz_message, 6 ) )
3120 free( p_stream->fmt.psz_description );
3121 p_stream->fmt.psz_description = strdup( psz_message + 6 );
3123 else if ( ! strncmp("Content-Type: ", psz_message, 14 ) )
3126 Ogg_ApplyContentType( p_stream, psz_message + 14, &b_foo, &b_foo );
3131 /* Return true if there's a skeleton exact match */
3132 bool Ogg_GetBoundsUsingSkeletonIndex( logical_stream_t *p_stream, int64_t i_time,
3133 int64_t *pi_lower, int64_t *pi_upper )
3135 if ( !p_stream || !p_stream->p_skel || !p_stream->p_skel->p_index )
3138 /* Validate range */
3139 if ( i_time < p_stream->p_skel->i_indexfirstnum
3140 * p_stream->p_skel->i_indexstampden ||
3141 i_time > p_stream->p_skel->i_indexlastnum
3142 * p_stream->p_skel->i_indexstampden ) return false;
3144 /* Then Lookup its index */
3145 unsigned const char *p_fwdbyte = p_stream->p_skel->p_index;
3150 } current = { 0, 0 }, prev = { -1, -1 };
3152 uint64_t i_keypoints_found = 0;
3154 while( p_fwdbyte < p_fwdbyte + p_stream->p_skel->i_index_size
3155 && i_keypoints_found < p_stream->p_skel->i_index )
3158 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
3159 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
3160 current.i_pos += i_val;
3161 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
3162 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
3163 current.i_time += i_val * p_stream->p_skel->i_indexstampden;
3164 if ( current.i_pos < 0 || current.i_time < 0 ) break;
3166 i_keypoints_found++;
3168 if ( i_time <= current.i_time )
3170 *pi_lower = prev.i_pos;
3171 *pi_upper = current.i_pos;
3172 return ( i_time == current.i_time );
3179 static uint32_t dirac_uint( bs_t *p_bs )
3181 uint32_t u_count = 0, u_value = 0;
3183 while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
3187 u_value |= bs_read( p_bs, 1 );
3190 return (1<<u_count) - 1 + u_value;
3193 static int dirac_bool( bs_t *p_bs )
3195 return bs_read( p_bs, 1 );
3198 static bool Ogg_ReadDiracHeader( logical_stream_t *p_stream,
3199 ogg_packet *p_oggpacket )
3201 static const struct {
3202 uint32_t u_n /* numerator */, u_d /* denominator */;
3203 } p_dirac_frate_tbl[] = { /* table 10.3 */
3204 {1,1}, /* this first value is never used */
3205 {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
3206 {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
3208 static const size_t u_dirac_frate_tbl = sizeof(p_dirac_frate_tbl)/sizeof(*p_dirac_frate_tbl);
3210 static const uint32_t pu_dirac_vidfmt_frate[] = { /* table C.1 */
3211 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
3213 static const size_t u_dirac_vidfmt_frate = sizeof(pu_dirac_vidfmt_frate)/sizeof(*pu_dirac_vidfmt_frate);
3217 p_stream->i_granule_shift = 22; /* not 32 */
3219 /* Backing up stream headers is not required -- seqhdrs are repeated
3220 * thoughout the stream at suitable decoding start points */
3221 p_stream->b_force_backup = false;
3223 /* read in useful bits from sequence header */
3224 bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes );
3225 bs_skip( &bs, 13*8); /* parse_info_header */
3226 dirac_uint( &bs ); /* major_version */
3227 dirac_uint( &bs ); /* minor_version */
3228 dirac_uint( &bs ); /* profile */
3229 dirac_uint( &bs ); /* level */
3231 uint32_t u_video_format = dirac_uint( &bs ); /* index */
3232 if( u_video_format >= u_dirac_vidfmt_frate )
3234 /* don't know how to parse this ogg dirac stream */
3238 if( dirac_bool( &bs ) )
3240 dirac_uint( &bs ); /* frame_width */
3241 dirac_uint( &bs ); /* frame_height */
3244 if( dirac_bool( &bs ) )
3246 dirac_uint( &bs ); /* chroma_format */
3249 if( dirac_bool( &bs ) )
3251 p_stream->special.dirac.b_interlaced = dirac_uint( &bs ); /* scan_format */
3254 p_stream->special.dirac.b_interlaced = false;
3256 uint32_t u_n = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_n;
3257 uint32_t u_d = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_d;
3258 u_d = __MAX( u_d, 1 );
3259 if( dirac_bool( &bs ) )
3261 uint32_t u_frame_rate_index = dirac_uint( &bs );
3262 if( u_frame_rate_index >= u_dirac_frate_tbl )
3264 /* something is wrong with this stream */
3267 u_n = p_dirac_frate_tbl[u_frame_rate_index].u_n;
3268 u_d = p_dirac_frate_tbl[u_frame_rate_index].u_d;
3269 if( u_frame_rate_index == 0 )
3271 u_n = dirac_uint( &bs ); /* frame_rate_numerator */
3272 u_d = dirac_uint( &bs ); /* frame_rate_denominator */
3275 p_stream->f_rate = (float) u_n / u_d;
3276 if ( p_stream->f_rate == 0 ) return false;
3278 /* probably is an ogg dirac es */
3279 p_stream->fmt.i_cat = VIDEO_ES;
3280 p_stream->fmt.i_codec = VLC_CODEC_DIRAC;