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_demux.h>
36 #include <vlc_input.h>
40 #include <vlc_codecs.h>
43 #include "xiph_metadata.h"
47 /*****************************************************************************
49 *****************************************************************************/
50 static int Open ( vlc_object_t * );
51 static void Close( vlc_object_t * );
54 set_shortname ( "OGG" )
55 set_description( N_("OGG demuxer" ) )
56 set_category( CAT_INPUT )
57 set_subcategory( SUBCAT_INPUT_DEMUX )
58 set_capability( "demux", 50 )
59 set_callbacks( Open, Close )
64 /*****************************************************************************
65 * Definitions of structures and functions used by this plugins
66 *****************************************************************************/
68 /* OggDS headers for the new header format (used in ogm files) */
73 } stream_header_video_t;
79 ogg_int16_t blockalign;
80 ogg_int32_t avgbytespersec;
81 } stream_header_audio_t;
88 ogg_int32_t size; /* size of the structure */
90 ogg_int64_t time_unit; /* in reference time */
91 ogg_int64_t samples_per_unit;
92 ogg_int32_t default_len; /* in media time */
94 ogg_int32_t buffersize;
95 ogg_int16_t bits_per_sample;
101 stream_header_video_t video;
103 stream_header_audio_t audio;
107 /*****************************************************************************
109 *****************************************************************************/
110 static int Demux ( demux_t * );
111 static int Control( demux_t *, int, va_list );
113 /* Bitstream manipulation */
114 static int Ogg_ReadPage ( demux_t *, ogg_page * );
115 static void Ogg_UpdatePCR ( logical_stream_t *, ogg_packet * );
116 static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet * );
117 static int Ogg_OpusPacketDuration( logical_stream_t *, ogg_packet * );
119 static int Ogg_BeginningOfStream( demux_t *p_demux );
120 static int Ogg_FindLogicalStreams( demux_t *p_demux );
121 static void Ogg_EndOfStream( demux_t *p_demux );
124 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream );
125 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream );
128 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers );
130 /* Logical bitstream headers */
131 static void Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * );
132 static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
133 static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
134 static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * );
135 static void Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
136 static void Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
137 static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
138 static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
139 static void Ogg_ReadSkeletonHeader( demux_t *, logical_stream_t *, ogg_packet * );
142 static void Ogg_ReadSkeletonBones( demux_t *, ogg_packet * );
143 static void Ogg_ReadSkeletonIndex( demux_t *, ogg_packet * );
144 static void Ogg_FreeSkeleton( ogg_skeleton_t * );
145 static void Ogg_ApplySkeleton( logical_stream_t * );
147 static void fill_channels_info(audio_format_t *audio)
149 static const int pi_channels_map[9] =
153 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
154 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
155 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
156 | AOUT_CHAN_REARRIGHT,
157 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
158 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
159 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
160 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
161 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
162 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
163 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
164 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
165 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
169 unsigned chans = audio->i_channels;
170 if (chans < sizeof(pi_channels_map) / sizeof(pi_channels_map[0]))
171 audio->i_physical_channels =
172 audio->i_original_channels = pi_channels_map[chans];
175 /*****************************************************************************
176 * Open: initializes ogg demux structures
177 *****************************************************************************/
178 static int Open( vlc_object_t * p_this )
180 demux_t *p_demux = (demux_t *)p_this;
182 const uint8_t *p_peek;
184 /* Check if we are dealing with an ogg stream */
185 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
186 if( !p_demux->b_force && memcmp( p_peek, "OggS", 4 ) )
192 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
196 p_sys->i_length = -1;
197 p_sys->b_preparsing_done = false;
199 /* Set exported functions */
200 p_demux->pf_demux = Demux;
201 p_demux->pf_control = Control;
203 /* Initialize the Ogg physical bitstream parser */
204 ogg_sync_init( &p_sys->oy );
207 TAB_INIT( p_sys->i_seekpoints, p_sys->pp_seekpoints );
210 while ( !p_sys->b_preparsing_done && p_demux->pf_demux( p_demux ) > 0 )
216 /*****************************************************************************
217 * Close: frees unused data
218 *****************************************************************************/
219 static void Close( vlc_object_t *p_this )
221 demux_t *p_demux = (demux_t *)p_this;
222 demux_sys_t *p_sys = p_demux->p_sys ;
224 /* Cleanup the bitstream parser */
225 ogg_sync_clear( &p_sys->oy );
227 Ogg_EndOfStream( p_demux );
229 if( p_sys->p_old_stream )
230 Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
235 /*****************************************************************************
236 * Demux: reads and demuxes data packets
237 *****************************************************************************
238 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
239 *****************************************************************************/
240 static int Demux( demux_t * p_demux )
242 demux_sys_t *p_sys = p_demux->p_sys;
243 ogg_packet oggpacket;
245 bool b_skipping = false;
248 int i_active_streams = p_sys->i_streams;
249 for ( int i=0; i < p_sys->i_streams; i++ )
251 if ( p_sys->pp_stream[i]->b_finished )
255 if ( i_active_streams == 0 )
257 if ( p_sys->i_streams ) /* All finished */
259 msg_Dbg( p_demux, "end of a group of logical streams" );
260 /* We keep the ES to try reusing it in Ogg_BeginningOfStream
261 * only 1 ES is supported (common case for ogg web radio) */
262 if( p_sys->i_streams == 1 )
264 p_sys->p_old_stream = p_sys->pp_stream[0];
265 TAB_CLEAN( p_sys->i_streams, p_sys->pp_stream );
267 Ogg_EndOfStream( p_demux );
270 if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS )
273 if ( ! p_sys->skeleton.major )
274 p_sys->b_preparsing_done = true;
276 /* Find the real duration */
277 stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
279 Oggseek_ProbeEnd( p_demux );
281 msg_Dbg( p_demux, "beginning of a group of logical streams" );
282 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 );
286 * The first data page of a physical stream is stored in the relevant logical stream
287 * in Ogg_FindLogicalStreams. Therefore, we must not read a page and only update the
288 * stream it belongs to if we haven't processed this first page yet. If we do, we
289 * will only process that first page whenever we find the second page for this stream.
290 * While this is fine for Vorbis and Theora, which are continuous codecs, which means
291 * the second page will arrive real quick, this is not fine for Kate, whose second
292 * data page will typically arrive much later.
293 * This means it is now possible to seek right at the start of a stream where the last
294 * logical stream is Kate, without having to wait for the second data page to unblock
295 * the first one, which is the one that triggers the 'no more headers to backup' code.
296 * And, as we all know, seeking without having backed up all headers is bad, since the
297 * codec will fail to initialize if it's missing its headers.
299 if( !p_sys->b_page_waiting)
302 * Demux an ogg page from the stream
304 if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS )
306 /* Test for End of Stream */
307 if( ogg_page_eos( &p_sys->current_page ) )
309 /* If we delayed restarting encoders/SET_ES_FMT for more
310 * skeleton provided configuration */
311 if ( p_sys->p_skelstream )
313 if ( p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
315 msg_Dbg( p_demux, "End of Skeleton" );
316 p_sys->b_preparsing_done = true;
317 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
319 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
320 if ( p_stream->b_have_updated_format )
322 p_stream->b_have_updated_format = false;
323 if ( p_stream->p_skel ) Ogg_ApplySkeleton( p_stream );
324 msg_Dbg( p_demux, "Resetting format for stream %d", i_stream );
325 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
326 p_stream->p_es, &p_stream->fmt );
333 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
335 if ( p_sys->pp_stream[i_stream]->i_serial_no == ogg_page_serialno( &p_sys->current_page ) )
337 p_sys->pp_stream[i_stream]->b_finished = true;
345 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
347 b_skipping |= p_sys->pp_stream[i_stream]->i_skip_frames;
350 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
352 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
354 /* if we've just pulled page, look for the right logical stream */
355 if( !p_sys->b_page_waiting )
357 if( p_sys->i_streams == 1 &&
358 ogg_page_serialno( &p_sys->current_page ) != p_stream->os.serialno )
360 msg_Err( p_demux, "Broken Ogg stream (serialno) mismatch" );
361 ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) );
363 p_stream->b_reinit = true;
364 p_stream->i_pcr = VLC_TS_0;
365 p_stream->i_interpolated_pcr = VLC_TS_0;
366 p_stream->i_previous_granulepos = -1;
367 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0);
370 /* Does fail if serialno differs */
371 if( ogg_stream_pagein( &p_stream->os, &p_sys->current_page ) != 0 )
378 /* clear the finished flag if pages after eos (ex: after a seek) */
379 if ( ! ogg_page_eos( &p_sys->current_page ) ) p_stream->b_finished = false;
382 if ( p_stream->fmt.i_cat == VIDEO_ES )
383 msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes eos %d ",
384 ogg_page_pageno( &p_sys->current_page ),
385 ogg_page_granulepos( &p_sys->current_page ),
386 ogg_page_packets( &p_sys->current_page ),
387 ogg_page_continued(&p_sys->current_page),
388 p_sys->current_page.body_len, p_sys->i_eos )
391 while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
393 /* Read info from any secondary header packets, if there are any */
394 if( p_stream->i_secondary_header_packets > 0 )
396 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA &&
397 oggpacket.bytes >= 7 &&
398 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
400 Ogg_ReadTheoraHeader( p_stream, &oggpacket );
401 p_stream->i_secondary_header_packets = 0;
403 else if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS &&
404 oggpacket.bytes >= 7 &&
405 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
407 Ogg_ReadVorbisHeader( p_stream, &oggpacket );
408 p_stream->i_secondary_header_packets = 0;
410 else if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
412 p_stream->i_secondary_header_packets = 0;
415 /* update start of data pointer */
416 p_stream->i_data_start = stream_Tell( p_demux->s );
419 /* If any streams have i_skip_frames, only decode (pre-roll)
420 * for those streams, but don't skip headers */
421 if ( b_skipping && p_stream->i_skip_frames == 0
422 && p_stream->i_secondary_header_packets ) continue;
424 if( p_stream->b_reinit )
426 if ( Oggseek_PacketPCRFixup( p_stream, &p_sys->current_page,
429 DemuxDebug( msg_Dbg( p_demux, "PCR fixup for %"PRId64,
430 ogg_page_granulepos( &p_sys->current_page ) ) );
434 /* If synchro is re-initialized we need to drop all the packets
435 * until we find a new dated one. */
436 Ogg_UpdatePCR( p_stream, &oggpacket );
439 if( p_stream->i_pcr >= 0 )
441 p_stream->b_reinit = false;
442 /* For Opus, trash the first 80 ms of decoded output as
443 well, to avoid blowing out speakers if we get unlucky.
444 Opus predicts content from prior frames, which can go
445 badly if we seek right where the stream goes from very
446 quiet to very loud. It will converge after a bit. */
447 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
449 ogg_int64_t start_time;
451 p_stream->i_skip_frames = 80*48;
452 /* Make sure we never play audio from within the
453 pre-skip at the beginning of the stream. */
455 Ogg_OpusPacketDuration( p_stream, &oggpacket );
456 start_time = p_stream->i_previous_granulepos;
459 start_time = start_time > duration ?
460 start_time - duration : 0;
462 if( p_stream->i_pre_skip > start_time )
464 p_stream->i_skip_frames +=
465 p_stream->i_pre_skip - start_time;
472 msg_Dbg(p_demux, "DEMUX DROPS PACKET (? / %d) pageno %ld granule %"PRId64,
473 ogg_page_packets( &p_sys->current_page ),
474 ogg_page_pageno( &p_sys->current_page ), oggpacket.granulepos );
477 p_stream->i_interpolated_pcr = -1;
478 p_stream->i_previous_granulepos = -1;
482 /* An Ogg/vorbis packet contains an end date granulepos */
483 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
484 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
485 p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
486 p_stream->fmt.i_codec == VLC_CODEC_FLAC )
488 if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
490 Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
494 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
495 VLC_TS_0 + p_stream->i_pcr );
501 DemuxDebug( if ( p_sys->b_seeked )
503 if ( Ogg_IsKeyFrame( p_stream, &oggpacket ) )
504 msg_Dbg(p_demux, "** DEMUX ON KEYFRAME **" );
506 ogg_int64_t iframe = ogg_page_granulepos( &p_sys->current_page ) >> p_stream->i_granule_shift;
507 ogg_int64_t pframe = ogg_page_granulepos( &p_sys->current_page ) - ( iframe << p_stream->i_granule_shift );
509 msg_Dbg(p_demux, "DEMUX PACKET (size %d) IS at iframe %"PRId64" pageno %ld pframe %"PRId64" OFFSET %"PRId64" PACKET NO %"PRId64" skipleft=%d",
510 ogg_page_packets( &p_sys->current_page ),
511 iframe, ogg_page_pageno( &p_sys->current_page ), pframe, p_sys->i_input_position, oggpacket.packetno, p_stream->i_skip_frames );
514 Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
517 DemuxDebug( p_sys->b_seeked = false; )
519 if( !p_sys->b_page_waiting )
523 /* if a page was waiting, it's now processed */
524 p_sys->b_page_waiting = false;
526 p_sys->b_preparsing_done = true;
529 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
531 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
533 if( p_stream->fmt.i_cat == SPU_ES )
535 if( p_stream->i_interpolated_pcr < 0 )
538 if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr )
539 p_sys->i_pcr = p_stream->i_interpolated_pcr;
542 if( p_sys->i_pcr >= 0 && ! b_skipping )
543 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
548 static void Ogg_ResetStreamHelper( demux_sys_t *p_sys )
550 for( int i = 0; i < p_sys->i_streams; i++ )
552 logical_stream_t *p_stream = p_sys->pp_stream[i];
554 /* we'll trash all the data until we find the next pcr */
555 p_stream->b_reinit = true;
556 p_stream->i_pcr = -1;
557 p_stream->i_interpolated_pcr = -1;
558 p_stream->i_previous_granulepos = -1;
559 ogg_stream_reset( &p_stream->os );
561 ogg_sync_reset( &p_sys->oy );
564 static logical_stream_t * Ogg_GetSelectedStream( demux_t *p_demux )
566 demux_sys_t *p_sys = p_demux->p_sys;
567 logical_stream_t *p_stream = NULL;
568 for( int i=0; i<p_sys->i_streams; i++ )
570 logical_stream_t *p_candidate = p_sys->pp_stream[i];
572 bool b_selected = false;
573 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
574 p_candidate->p_es, &b_selected );
575 if ( !b_selected ) continue;
577 if ( !p_stream && p_candidate->fmt.i_cat == AUDIO_ES )
579 p_stream = p_candidate;
580 continue; /* Try to find video anyway */
583 if ( p_candidate->fmt.i_cat == VIDEO_ES )
585 p_stream = p_candidate;
592 /*****************************************************************************
594 *****************************************************************************/
595 static int Control( demux_t *p_demux, int i_query, va_list args )
597 demux_sys_t *p_sys = p_demux->p_sys;
606 p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t* );
608 vlc_meta_Merge( p_meta, p_sys->p_meta );
611 case DEMUX_HAS_UNSUPPORTED_META:
612 pb_bool = (bool*)va_arg( args, bool* );
617 pi64 = (int64_t*)va_arg( args, int64_t * );
618 *pi64 = p_sys->i_pcr;
622 i64 = (int64_t)va_arg( args, int64_t );
623 logical_stream_t *p_stream = Ogg_GetSelectedStream( p_demux );
626 msg_Err( p_demux, "No selected seekable stream found" );
629 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
630 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
632 Ogg_ResetStreamHelper( p_sys );
633 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
640 case DEMUX_GET_ATTACHMENTS:
642 input_attachment_t ***ppp_attach =
643 (input_attachment_t***)va_arg( args, input_attachment_t*** );
644 int *pi_int = (int*)va_arg( args, int * );
646 if( p_sys->i_attachments <= 0 )
649 *pi_int = p_sys->i_attachments;
650 *ppp_attach = xmalloc( sizeof(input_attachment_t*) * p_sys->i_attachments );
651 for( int i = 0; i < p_sys->i_attachments; i++ )
652 (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
656 case DEMUX_GET_POSITION:
657 pf = (double*)va_arg( args, double * );
658 if( p_sys->i_length > 0 )
660 *pf = (double) p_sys->i_pcr /
661 (double) ( p_sys->i_length * (mtime_t)1000000 );
663 else if( stream_Size( p_demux->s ) > 0 )
665 i64 = stream_Tell( p_demux->s );
666 *pf = (double) i64 / stream_Size( p_demux->s );
671 case DEMUX_SET_POSITION:
672 /* forbid seeking if we haven't initialized all logical bitstreams yet;
673 if we allowed, some headers would not get backed up and decoder init
674 would fail, making that logical stream unusable */
675 for ( int i=0; i< p_sys->i_streams; i++ )
677 if ( p_sys->pp_stream[i]->b_initializing )
681 p_stream = Ogg_GetSelectedStream( p_demux );
684 msg_Err( p_demux, "No selected seekable stream found" );
688 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
690 f = (double)va_arg( args, double );
691 if ( p_sys->i_length <= 0 || !b /* || ! ACCESS_CAN_FASTSEEK */ )
693 Ogg_ResetStreamHelper( p_sys );
694 Oggseek_BlindSeektoPosition( p_demux, p_stream, f, b );
698 assert( p_sys->i_length > 0 );
699 i64 = CLOCK_FREQ * p_sys->i_length * f;
700 Ogg_ResetStreamHelper( p_sys );
701 if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, i64 ) >= 0 )
703 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
710 case DEMUX_GET_LENGTH:
711 if ( p_sys->i_length < 0 )
712 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
714 pi64 = (int64_t*)va_arg( args, int64_t * );
715 *pi64 = p_sys->i_length * 1000000;
718 case DEMUX_GET_TITLE_INFO:
720 input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
721 int *pi_int = (int*)va_arg( args, int* );
722 int *pi_title_offset = (int*)va_arg( args, int* );
723 int *pi_seekpoint_offset = (int*)va_arg( args, int* );
725 if( p_sys->i_seekpoints > 0 )
728 *ppp_title = malloc( sizeof( input_title_t* ) );
729 input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
730 for( int i = 0; i < p_sys->i_seekpoints; i++ )
732 seekpoint_t *p_seekpoint_copy = vlc_seekpoint_Duplicate( p_sys->pp_seekpoints[i] );
733 if ( likely( p_seekpoint_copy ) )
734 TAB_APPEND( p_title->i_seekpoint, p_title->seekpoint, p_seekpoint_copy );
736 *pi_title_offset = 0;
737 *pi_seekpoint_offset = 0;
741 case DEMUX_SET_TITLE:
743 const int i_title = (int)va_arg( args, int );
748 case DEMUX_SET_SEEKPOINT:
750 const int i_seekpoint = (int)va_arg( args, int );
751 if( i_seekpoint > p_sys->i_seekpoints )
754 for ( int i=0; i< p_sys->i_streams; i++ )
756 if ( p_sys->pp_stream[i]->b_initializing )
760 i64 = p_sys->pp_seekpoints[i_seekpoint]->i_time_offset;
762 p_stream = Ogg_GetSelectedStream( p_demux );
765 msg_Err( p_demux, "No selected seekable stream found" );
769 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
770 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
772 Ogg_ResetStreamHelper( p_sys );
773 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
775 p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
776 p_demux->info.i_seekpoint = i_seekpoint;
784 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
789 /****************************************************************************
790 * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
791 ****************************************************************************
792 * Returns VLC_SUCCESS if a page has been read. An error might happen if we
793 * are at the end of stream.
794 ****************************************************************************/
795 static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
797 demux_sys_t *p_ogg = p_demux->p_sys ;
801 while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
803 p_buffer = ogg_sync_buffer( &p_ogg->oy, OGGSEEK_BYTES_TO_READ );
805 i_read = stream_Read( p_demux->s, p_buffer, OGGSEEK_BYTES_TO_READ );
809 ogg_sync_wrote( &p_ogg->oy, i_read );
815 /****************************************************************************
816 * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
818 ****************************************************************************/
819 static void Ogg_UpdatePCR( logical_stream_t *p_stream,
820 ogg_packet *p_oggpacket )
822 p_stream->i_end_trim = 0;
824 /* Convert the granulepos into a pcr */
825 if( p_oggpacket->granulepos >= 0 )
827 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA ||
828 p_stream->fmt.i_codec == VLC_CODEC_KATE ||
829 p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
831 p_stream->i_pcr = Oggseek_GranuleToAbsTimestamp( p_stream,
832 p_oggpacket->granulepos, true );
837 sample = p_oggpacket->granulepos;
838 if( p_oggpacket->e_o_s &&
839 p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
840 p_stream->i_previous_granulepos >= 0 )
843 duration = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
846 ogg_int64_t end_sample;
847 end_sample = p_stream->i_previous_granulepos + duration;
848 if( end_sample > sample )
849 p_stream->i_end_trim = (int)(end_sample - sample);
852 if (sample >= p_stream->i_pre_skip)
853 sample -= p_stream->i_pre_skip;
856 p_stream->i_pcr = sample * CLOCK_FREQ / p_stream->f_rate;
859 p_stream->i_pcr += VLC_TS_0;
860 p_stream->i_interpolated_pcr = p_stream->i_pcr;
865 p_stream->i_pcr = -1;
867 /* no granulepos available, try to interpolate the pcr.
868 * If we can't then don't touch the old value. */
869 if( p_stream->fmt.i_cat == VIDEO_ES )
870 /* 1 frame per packet */
871 p_stream->i_interpolated_pcr += (CLOCK_FREQ / p_stream->f_rate);
872 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
873 p_stream->i_previous_granulepos >= 0 &&
875 Ogg_OpusPacketDuration( p_stream, p_oggpacket ) ) > 0 )
878 p_oggpacket->granulepos =
879 p_stream->i_previous_granulepos + duration;
880 sample = p_oggpacket->granulepos;
881 if (sample >= p_stream->i_pre_skip)
882 sample -= p_stream->i_pre_skip;
885 p_stream->i_interpolated_pcr =
886 VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
888 else if( p_stream->fmt.i_bitrate )
890 p_stream->i_interpolated_pcr +=
891 ( p_oggpacket->bytes * CLOCK_FREQ /
892 p_stream->fmt.i_bitrate / 8 );
895 p_stream->i_previous_granulepos = p_oggpacket->granulepos;
898 /****************************************************************************
899 * Ogg_DecodePacket: Decode an Ogg packet.
900 ****************************************************************************/
901 static void Ogg_DecodePacket( demux_t *p_demux,
902 logical_stream_t *p_stream,
903 ogg_packet *p_oggpacket )
907 int i_header_len = 0;
908 mtime_t i_pts = -1, i_interpolated_pts;
909 demux_sys_t *p_ogg = p_demux->p_sys;
911 if( p_oggpacket->bytes >= 7 &&
912 ! memcmp ( p_oggpacket->packet, "Annodex", 7 ) )
914 /* it's an Annodex packet -- skip it (do nothing) */
917 else if( p_oggpacket->bytes >= 7 &&
918 ! memcmp ( p_oggpacket->packet, "AnxData", 7 ) )
920 /* it's an AnxData packet -- skip it (do nothing) */
923 else if( p_oggpacket->bytes >= 8 &&
924 ! memcmp ( p_oggpacket->packet, "fisbone", 8 ) )
926 Ogg_ReadSkeletonBones( p_demux, p_oggpacket );
929 else if( p_oggpacket->bytes >= 6 &&
930 ! memcmp ( p_oggpacket->packet, "index", 6 ) )
932 Ogg_ReadSkeletonIndex( p_demux, p_oggpacket );
936 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT && p_oggpacket->bytes > 0 &&
937 p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
939 /* Check the ES is selected */
940 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
941 p_stream->p_es, &b_selected );
943 if( p_stream->b_force_backup )
946 p_stream->i_packets_backup++;
947 switch( p_stream->fmt.i_codec )
949 case VLC_CODEC_VORBIS:
950 case VLC_CODEC_THEORA:
951 if( p_stream->i_packets_backup == 3 )
952 p_stream->b_force_backup = false;
956 case VLC_CODEC_SPEEX:
957 if( p_stream->i_packets_backup == 2 + p_stream->i_extra_headers_packets )
958 p_stream->b_force_backup = false;
963 if( p_stream->i_packets_backup == 2 )
964 p_stream->b_force_backup = false;
969 if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )
971 Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );
972 p_stream->b_force_backup = false;
974 else if( p_stream->fmt.audio.i_rate )
976 p_stream->b_force_backup = false;
977 if( p_oggpacket->bytes >= 9 )
979 p_oggpacket->packet += 9;
980 p_oggpacket->bytes -= 9;
987 if( p_stream->i_packets_backup == p_stream->i_kate_num_headers )
988 p_stream->b_force_backup = false;
993 p_stream->b_force_backup = false;
998 /* Backup the ogg packet (likely an header packet) */
1001 void *p_org = p_stream->p_headers;
1002 p_stream->i_headers += p_oggpacket->bytes;
1003 p_stream->p_headers = realloc( p_stream->p_headers, p_stream->i_headers );
1004 if( p_stream->p_headers )
1006 memcpy( (unsigned char *)p_stream->p_headers + p_stream->i_headers - p_oggpacket->bytes,
1007 p_oggpacket->packet, p_oggpacket->bytes );
1011 #warning Memory leak
1012 p_stream->i_headers = 0;
1013 p_stream->p_headers = NULL;
1017 else if( xiph_AppendHeaders( &p_stream->i_headers, &p_stream->p_headers,
1018 p_oggpacket->bytes, p_oggpacket->packet ) )
1020 p_stream->i_headers = 0;
1021 p_stream->p_headers = NULL;
1023 if( p_stream->i_headers > 0 )
1025 if( !p_stream->b_force_backup )
1027 /* Last header received, commit changes */
1028 free( p_stream->fmt.p_extra );
1030 p_stream->fmt.i_extra = p_stream->i_headers;
1031 p_stream->fmt.p_extra = malloc( p_stream->i_headers );
1032 if( p_stream->fmt.p_extra )
1033 memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
1034 p_stream->i_headers );
1036 p_stream->fmt.i_extra = 0;
1038 if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
1040 if ( p_ogg->p_skelstream )
1042 /* We delay until eos is reached on skeleton.
1043 * There should only be headers, as no data page is
1044 * allowed before skeleton's eos.
1045 * Skeleton data is appended to fmt on skeleton eos.
1047 p_stream->b_have_updated_format = true;
1051 /* Otherwise we set config from first headers */
1052 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
1053 p_stream->p_es, &p_stream->fmt );
1056 if( p_stream->i_headers > 0 )
1057 Ogg_ExtractMeta( p_demux, & p_stream->fmt,
1058 p_stream->p_headers, p_stream->i_headers );
1060 /* we're not at BOS anymore for this logical stream */
1061 p_stream->b_initializing = false;
1065 b_selected = false; /* Discard the header packet */
1068 /* Convert the pcr into a pts */
1069 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
1070 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
1071 p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
1072 p_stream->fmt.i_codec == VLC_CODEC_FLAC )
1074 if( p_stream->i_pcr >= 0 )
1076 /* This is for streams where the granulepos of the header packets
1077 * doesn't match these of the data packets (eg. ogg web radios). */
1078 if( p_stream->i_previous_pcr == 0 &&
1079 p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
1082 /* Call the pace control */
1083 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
1084 VLC_TS_0 + p_stream->i_pcr );
1087 p_stream->i_previous_pcr = p_stream->i_pcr;
1089 /* The granulepos is the end date of the sample */
1090 i_pts = p_stream->i_pcr;
1094 /* Convert the granulepos into the next pcr */
1095 i_interpolated_pts = p_stream->i_interpolated_pcr;
1096 Ogg_UpdatePCR( p_stream, p_oggpacket );
1098 /* SPU streams are typically discontinuous, do not mind large gaps */
1099 if( p_stream->fmt.i_cat != SPU_ES )
1101 if( p_stream->i_pcr >= 0 )
1103 /* This is for streams where the granulepos of the header packets
1104 * doesn't match these of the data packets (eg. ogg web radios). */
1105 if( p_stream->i_previous_pcr == 0 &&
1106 p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
1109 /* Call the pace control */
1110 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_stream->i_pcr );
1115 if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
1116 p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
1117 p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
1118 p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
1119 p_stream->i_pcr >= 0 )
1121 p_stream->i_previous_pcr = p_stream->i_pcr;
1123 /* The granulepos is the start date of the sample */
1124 i_pts = p_stream->i_pcr;
1129 /* This stream isn't currently selected so we don't need to decode it,
1130 * but we did need to store its pcr as it might be selected later on */
1134 if( !( p_block = block_Alloc( p_oggpacket->bytes ) ) ) return;
1137 /* may need to preroll after a seek */
1138 if ( p_stream->i_skip_frames > 0 )
1140 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1143 duration = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
1144 if( p_stream->i_skip_frames > duration )
1146 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1147 p_block->i_nb_samples = 0;
1148 p_stream->i_skip_frames -= duration;
1152 p_block->i_nb_samples = duration - p_stream->i_skip_frames;
1153 if( p_stream->i_previous_granulepos >=
1154 p_block->i_nb_samples + p_stream->i_pre_skip )
1156 i_pts = VLC_TS_0 + (p_stream->i_previous_granulepos
1157 - p_block->i_nb_samples - p_stream->i_pre_skip) *
1158 CLOCK_FREQ / p_stream->f_rate;
1160 p_stream->i_skip_frames = 0;
1165 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1166 p_stream->i_skip_frames--;
1169 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1170 p_block->i_nb_samples = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
1174 if( i_pts == VLC_TS_INVALID ) i_pts = VLC_TS_0;
1175 else if( i_pts == -1 && i_interpolated_pts == VLC_TS_INVALID )
1177 else if( i_pts == -1 && (p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_codec == VLC_CODEC_OPUS) )
1178 i_pts = i_interpolated_pts; /* FIXME : why is this incorrect for vorbis? */
1179 else if( i_pts == -1 ) i_pts = VLC_TS_INVALID;
1181 if( p_stream->fmt.i_cat == AUDIO_ES )
1183 p_block->i_dts = p_block->i_pts = i_pts;
1184 /* Blatant abuse of the i_length field. */
1185 p_block->i_length = p_stream->i_end_trim;
1187 else if( p_stream->fmt.i_cat == SPU_ES )
1189 p_block->i_dts = p_block->i_pts = i_pts;
1190 p_block->i_length = 0;
1192 else if( p_stream->fmt.i_codec == VLC_CODEC_THEORA )
1194 p_block->i_dts = p_block->i_pts = i_pts;
1195 if( (p_oggpacket->granulepos & ((1<<p_stream->i_granule_shift)-1)) == 0 )
1197 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
1200 else if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
1202 ogg_int64_t dts = p_oggpacket->granulepos >> 31;
1203 ogg_int64_t delay = (p_oggpacket->granulepos >> 9) & 0x1fff;
1205 uint64_t u_pnum = dts + delay;
1207 p_block->i_dts = p_stream->i_pcr;
1208 p_block->i_pts = VLC_TS_INVALID;
1209 /* NB, OggDirac granulepos values are in units of 2*picturerate */
1211 /* granulepos for dirac is possibly broken, this value should be ignored */
1212 if( -1 != p_oggpacket->granulepos )
1213 p_block->i_pts = u_pnum * CLOCK_FREQ / p_stream->f_rate / 2;
1217 p_block->i_dts = i_pts;
1218 p_block->i_pts = VLC_TS_INVALID;
1221 if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
1222 p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
1223 p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
1224 p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
1225 p_stream->fmt.i_codec != VLC_CODEC_TARKIN &&
1226 p_stream->fmt.i_codec != VLC_CODEC_THEORA &&
1227 p_stream->fmt.i_codec != VLC_CODEC_CMML &&
1228 p_stream->fmt.i_codec != VLC_CODEC_DIRAC &&
1229 p_stream->fmt.i_codec != VLC_CODEC_KATE )
1231 if( p_oggpacket->bytes <= 0 )
1233 msg_Dbg( p_demux, "discarding 0 sized packet" );
1234 block_Release( p_block );
1237 /* We remove the header from the packet */
1238 i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
1239 i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
1241 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT)
1243 /* But with subtitles we need to retrieve the duration first */
1244 int i, lenbytes = 0;
1246 if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
1248 for( i = 0, lenbytes = 0; i < i_header_len; i++ )
1250 lenbytes = lenbytes << 8;
1251 lenbytes += *(p_oggpacket->packet + i_header_len - i);
1254 if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
1255 ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
1256 p_oggpacket->packet[i_header_len + 1] != 0 &&
1257 p_oggpacket->packet[i_header_len + 1] != '\n' &&
1258 p_oggpacket->packet[i_header_len + 1] != '\r' ) )
1260 p_block->i_length = (mtime_t)lenbytes * 1000;
1265 if( p_block->i_buffer >= (unsigned int)i_header_len )
1266 p_block->i_buffer -= i_header_len;
1268 p_block->i_buffer = 0;
1271 if( p_stream->fmt.i_codec == VLC_CODEC_TARKIN )
1273 /* FIXME: the biggest hack I've ever done */
1274 msg_Warn( p_demux, "tarkin pts: %"PRId64", granule: %"PRId64,
1275 p_block->i_pts, p_block->i_dts );
1279 memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
1280 p_oggpacket->bytes - i_header_len );
1282 assert( p_ogg->b_preparsing_done );
1283 es_out_Send( p_demux->out, p_stream->p_es, p_block );
1286 /* Re-implemented to avoid linking against libopus from the demuxer. */
1287 static int Ogg_OpusPacketDuration( logical_stream_t *p_stream,
1288 ogg_packet *p_oggpacket )
1290 static const int silk_fs_div[4] = { 6000, 3000, 1500, 1000 };
1296 if( p_oggpacket->bytes < 1 )
1297 return VLC_EGENERIC;
1298 toc = p_oggpacket->packet[0];
1309 if( p_oggpacket->bytes < 2 )
1310 return VLC_EGENERIC;
1311 nframes = p_oggpacket->packet[1]&0x3F;
1314 i_rate = (int)p_stream->fmt.audio.i_rate;
1316 frame_size = (i_rate << (toc >> 3 & 3)) / 400;
1317 else if( ( toc&0x60 ) == 0x60 )
1318 frame_size = i_rate/(100 >> (toc >> 3 & 1));
1320 frame_size = i_rate*60 / silk_fs_div[toc >> 3 & 3];
1321 nsamples = nframes*frame_size;
1322 if( nsamples*25 > i_rate*3 )
1323 return VLC_EGENERIC;
1327 /****************************************************************************
1328 * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
1329 * stream and fill p_ogg.
1330 *****************************************************************************
1331 * The initial page of a logical stream is marked as a 'bos' page.
1332 * Furthermore, the Ogg specification mandates that grouped bitstreams begin
1333 * together and all of the initial pages must appear before any data pages.
1335 * On success this function returns VLC_SUCCESS.
1336 ****************************************************************************/
1337 static int Ogg_FindLogicalStreams( demux_t *p_demux )
1339 demux_sys_t *p_ogg = p_demux->p_sys ;
1340 ogg_packet oggpacket;
1343 p_ogg->i_total_length = stream_Size ( p_demux->s );
1344 msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_length );
1347 while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS )
1350 if( ogg_page_bos( &p_ogg->current_page ) )
1353 /* All is wonderful in our fine fine little world.
1354 * We found the beginning of our first logical stream. */
1355 while( ogg_page_bos( &p_ogg->current_page ) )
1357 logical_stream_t *p_stream;
1359 p_stream = malloc( sizeof(logical_stream_t) );
1360 if( unlikely( !p_stream ) )
1363 TAB_APPEND( p_ogg->i_streams, p_ogg->pp_stream, p_stream );
1365 memset( p_stream, 0, sizeof(logical_stream_t) );
1367 es_format_Init( &p_stream->fmt, 0, 0 );
1368 es_format_Init( &p_stream->fmt_old, 0, 0 );
1370 /* Setup the logical stream */
1371 p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page );
1372 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
1374 /* Extract the initial header from the first page and verify
1375 * the codec type of this Ogg bitstream */
1376 if( ogg_stream_pagein( &p_stream->os, &p_ogg->current_page ) < 0 )
1378 /* error. stream version mismatch perhaps */
1379 msg_Err( p_demux, "error reading first page of "
1380 "Ogg bitstream data" );
1381 return VLC_EGENERIC;
1384 /* FIXME: check return value */
1385 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
1387 /* Check for Vorbis header */
1388 if( oggpacket.bytes >= 7 &&
1389 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
1391 Ogg_ReadVorbisHeader( p_stream, &oggpacket );
1392 msg_Dbg( p_demux, "found vorbis header" );
1394 /* Check for Speex header */
1395 else if( oggpacket.bytes >= 5 &&
1396 ! memcmp( oggpacket.packet, "Speex", 5 ) )
1398 Ogg_ReadSpeexHeader( p_stream, &oggpacket );
1399 msg_Dbg( p_demux, "found speex header, channels: %i, "
1400 "rate: %i, bitrate: %i",
1401 p_stream->fmt.audio.i_channels,
1402 (int)p_stream->f_rate, p_stream->fmt.i_bitrate );
1404 /* Check for Opus header */
1405 else if( oggpacket.bytes >= 8 &&
1406 ! memcmp( oggpacket.packet, "OpusHead", 8 ) )
1408 Ogg_ReadOpusHeader( p_stream, &oggpacket );
1409 msg_Dbg( p_demux, "found opus header, channels: %i, "
1411 p_stream->fmt.audio.i_channels,
1412 (int)p_stream->i_pre_skip);
1413 p_stream->i_skip_frames = p_stream->i_pre_skip;
1415 /* Check for Flac header (< version 1.1.1) */
1416 else if( oggpacket.bytes >= 4 &&
1417 ! memcmp( oggpacket.packet, "fLaC", 4 ) )
1419 msg_Dbg( p_demux, "found FLAC header" );
1421 /* Grrrr!!!! Did they really have to put all the
1422 * important info in the second header packet!!!
1423 * (STREAMINFO metadata is in the following packet) */
1424 p_stream->b_force_backup = true;
1426 p_stream->fmt.i_cat = AUDIO_ES;
1427 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1429 /* Check for Flac header (>= version 1.1.1) */
1430 else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
1431 ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
1432 ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
1434 int i_packets = ((int)oggpacket.packet[7]) << 8 |
1435 oggpacket.packet[8];
1436 msg_Dbg( p_demux, "found FLAC header version %i.%i "
1437 "(%i header packets)",
1438 oggpacket.packet[5], oggpacket.packet[6],
1441 p_stream->b_force_backup = true;
1443 p_stream->fmt.i_cat = AUDIO_ES;
1444 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1445 oggpacket.packet += 13; oggpacket.bytes -= 13;
1446 Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket );
1448 /* Check for Theora header */
1449 else if( oggpacket.bytes >= 7 &&
1450 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
1452 Ogg_ReadTheoraHeader( p_stream, &oggpacket );
1455 "found theora header, bitrate: %i, rate: %f",
1456 p_stream->fmt.i_bitrate, p_stream->f_rate );
1458 /* Check for Dirac header */
1459 else if( ( oggpacket.bytes >= 5 &&
1460 ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) ||
1461 ( oggpacket.bytes >= 9 &&
1462 ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) )
1464 if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) )
1465 msg_Dbg( p_demux, "found dirac header" );
1468 msg_Warn( p_demux, "found dirac header isn't decodable" );
1473 /* Check for Tarkin header */
1474 else if( oggpacket.bytes >= 7 &&
1475 ! memcmp( &oggpacket.packet[1], "tarkin", 6 ) )
1479 msg_Dbg( p_demux, "found tarkin header" );
1480 p_stream->fmt.i_cat = VIDEO_ES;
1481 p_stream->fmt.i_codec = VLC_CODEC_TARKIN;
1483 /* Cheat and get additionnal info ;) */
1484 oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
1485 oggpack_adv( &opb, 88 );
1486 oggpack_adv( &opb, 104 );
1487 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
1488 p_stream->f_rate = 2; /* FIXME */
1490 "found tarkin header, bitrate: %i, rate: %f",
1491 p_stream->fmt.i_bitrate, p_stream->f_rate );
1493 /* Check for Annodex header */
1494 else if( oggpacket.bytes >= 7 &&
1495 ! memcmp( oggpacket.packet, "Annodex", 7 ) )
1497 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1498 /* kill annodex track */
1502 /* Check for Annodex header */
1503 else if( oggpacket.bytes >= 7 &&
1504 ! memcmp( oggpacket.packet, "AnxData", 7 ) )
1506 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1508 /* Check for Kate header */
1509 else if( oggpacket.bytes >= 8 &&
1510 ! memcmp( &oggpacket.packet[1], "kate\0\0\0", 7 ) )
1512 Ogg_ReadKateHeader( p_stream, &oggpacket );
1513 msg_Dbg( p_demux, "found kate header" );
1515 /* Check for OggDS */
1516 else if( oggpacket.bytes >= 142 &&
1517 !memcmp( &oggpacket.packet[1],
1518 "Direct Show Samples embedded in Ogg", 35 ))
1520 /* Old header type */
1521 p_stream->b_oggds = true;
1522 /* Check for video header (old format) */
1523 if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
1524 oggpacket.bytes >= 184 )
1526 p_stream->fmt.i_cat = VIDEO_ES;
1527 p_stream->fmt.i_codec =
1528 VLC_FOURCC( oggpacket.packet[68],
1529 oggpacket.packet[69],
1530 oggpacket.packet[70],
1531 oggpacket.packet[71] );
1532 msg_Dbg( p_demux, "found video header of type: %.4s",
1533 (char *)&p_stream->fmt.i_codec );
1535 p_stream->fmt.video.i_frame_rate = 10000000;
1536 p_stream->fmt.video.i_frame_rate_base =
1537 GetQWLE((oggpacket.packet+164));
1538 p_stream->f_rate = 10000000.0 /
1539 GetQWLE((oggpacket.packet+164));
1540 p_stream->fmt.video.i_bits_per_pixel =
1541 GetWLE((oggpacket.packet+182));
1542 if( !p_stream->fmt.video.i_bits_per_pixel )
1544 p_stream->fmt.video.i_bits_per_pixel = 24;
1545 p_stream->fmt.video.i_width =
1546 GetDWLE((oggpacket.packet+176));
1547 p_stream->fmt.video.i_height =
1548 GetDWLE((oggpacket.packet+180));
1551 "fps: %f, width:%i; height:%i, bitcount:%i",
1553 p_stream->fmt.video.i_width,
1554 p_stream->fmt.video.i_height,
1555 p_stream->fmt.video.i_bits_per_pixel);
1558 /* Check for audio header (old format) */
1559 else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
1562 unsigned int i_format_tag;
1564 p_stream->fmt.i_cat = AUDIO_ES;
1566 i_extra_size = GetWLE((oggpacket.packet+140));
1567 if( i_extra_size > 0 && i_extra_size < oggpacket.bytes - 142 )
1569 p_stream->fmt.i_extra = i_extra_size;
1570 p_stream->fmt.p_extra = malloc( i_extra_size );
1571 if( p_stream->fmt.p_extra )
1572 memcpy( p_stream->fmt.p_extra,
1573 oggpacket.packet + 142, i_extra_size );
1575 p_stream->fmt.i_extra = 0;
1578 i_format_tag = GetWLE((oggpacket.packet+124));
1579 p_stream->fmt.audio.i_channels =
1580 GetWLE((oggpacket.packet+126));
1581 fill_channels_info(&p_stream->fmt.audio);
1582 p_stream->f_rate = p_stream->fmt.audio.i_rate =
1583 GetDWLE((oggpacket.packet+128));
1584 p_stream->fmt.i_bitrate =
1585 GetDWLE((oggpacket.packet+132)) * 8;
1586 p_stream->fmt.audio.i_blockalign =
1587 GetWLE((oggpacket.packet+136));
1588 p_stream->fmt.audio.i_bitspersample =
1589 GetWLE((oggpacket.packet+138));
1591 wf_tag_to_fourcc( i_format_tag,
1592 &p_stream->fmt.i_codec, 0 );
1594 if( p_stream->fmt.i_codec ==
1595 VLC_FOURCC('u','n','d','f') )
1597 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1598 ( i_format_tag >> 8 ) & 0xff,
1599 i_format_tag & 0xff );
1602 msg_Dbg( p_demux, "found audio header of type: %.4s",
1603 (char *)&p_stream->fmt.i_codec );
1604 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1605 "%dbits/sample %dkb/s",
1607 p_stream->fmt.audio.i_channels,
1608 p_stream->fmt.audio.i_rate,
1609 p_stream->fmt.audio.i_bitspersample,
1610 p_stream->fmt.i_bitrate / 1024 );
1615 msg_Dbg( p_demux, "stream %d has an old header "
1616 "but is of an unknown type", p_ogg->i_streams-1 );
1621 /* Check for OggDS */
1622 else if( oggpacket.bytes >= 44+1 &&
1623 (*oggpacket.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER )
1625 stream_header_t tmp;
1626 stream_header_t *st = &tmp;
1628 p_stream->b_oggds = true;
1630 memcpy( st->streamtype, &oggpacket.packet[1+0], 8 );
1631 memcpy( st->subtype, &oggpacket.packet[1+8], 4 );
1632 st->size = GetDWLE( &oggpacket.packet[1+12] );
1633 st->time_unit = GetQWLE( &oggpacket.packet[1+16] );
1634 st->samples_per_unit = GetQWLE( &oggpacket.packet[1+24] );
1635 st->default_len = GetDWLE( &oggpacket.packet[1+32] );
1636 st->buffersize = GetDWLE( &oggpacket.packet[1+36] );
1637 st->bits_per_sample = GetWLE( &oggpacket.packet[1+40] ); // (padding 2)
1639 /* Check for video header (new format) */
1640 if( !strncmp( st->streamtype, "video", 5 ) &&
1641 oggpacket.bytes >= 52+1 )
1643 st->sh.video.width = GetDWLE( &oggpacket.packet[1+44] );
1644 st->sh.video.height = GetDWLE( &oggpacket.packet[1+48] );
1646 p_stream->fmt.i_cat = VIDEO_ES;
1648 /* We need to get rid of the header packet */
1649 ogg_stream_packetout( &p_stream->os, &oggpacket );
1651 p_stream->fmt.i_codec =
1652 VLC_FOURCC( st->subtype[0], st->subtype[1],
1653 st->subtype[2], st->subtype[3] );
1654 msg_Dbg( p_demux, "found video header of type: %.4s",
1655 (char *)&p_stream->fmt.i_codec );
1657 p_stream->fmt.video.i_frame_rate = 10000000;
1658 p_stream->fmt.video.i_frame_rate_base = st->time_unit;
1659 if( st->time_unit <= 0 )
1660 st->time_unit = 400000;
1661 p_stream->f_rate = 10000000.0 / st->time_unit;
1662 p_stream->fmt.video.i_bits_per_pixel = st->bits_per_sample;
1663 p_stream->fmt.video.i_width = st->sh.video.width;
1664 p_stream->fmt.video.i_height = st->sh.video.height;
1667 "fps: %f, width:%i; height:%i, bitcount:%i",
1669 p_stream->fmt.video.i_width,
1670 p_stream->fmt.video.i_height,
1671 p_stream->fmt.video.i_bits_per_pixel );
1673 /* Check for audio header (new format) */
1674 else if( !strncmp( st->streamtype, "audio", 5 ) &&
1675 oggpacket.bytes >= 56+1 )
1681 st->sh.audio.channels = GetWLE( &oggpacket.packet[1+44] );
1682 st->sh.audio.blockalign = GetWLE( &oggpacket.packet[1+48] );
1683 st->sh.audio.avgbytespersec = GetDWLE( &oggpacket.packet[1+52] );
1685 p_stream->fmt.i_cat = AUDIO_ES;
1687 /* We need to get rid of the header packet */
1688 ogg_stream_packetout( &p_stream->os, &oggpacket );
1690 i_extra_size = st->size - 56;
1692 if( i_extra_size > 0 &&
1693 i_extra_size < oggpacket.bytes - 1 - 56 )
1695 p_stream->fmt.i_extra = i_extra_size;
1696 p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
1697 if( p_stream->fmt.p_extra )
1698 memcpy( p_stream->fmt.p_extra, oggpacket.packet + 57,
1699 p_stream->fmt.i_extra );
1701 p_stream->fmt.i_extra = 0;
1704 memcpy( p_buffer, st->subtype, 4 );
1706 i_format_tag = strtol(p_buffer,NULL,16);
1707 p_stream->fmt.audio.i_channels = st->sh.audio.channels;
1708 fill_channels_info(&p_stream->fmt.audio);
1709 if( st->time_unit <= 0 )
1710 st->time_unit = 10000000;
1711 p_stream->f_rate = p_stream->fmt.audio.i_rate = st->samples_per_unit * 10000000 / st->time_unit;
1712 p_stream->fmt.i_bitrate = st->sh.audio.avgbytespersec * 8;
1713 p_stream->fmt.audio.i_blockalign = st->sh.audio.blockalign;
1714 p_stream->fmt.audio.i_bitspersample = st->bits_per_sample;
1716 wf_tag_to_fourcc( i_format_tag,
1717 &p_stream->fmt.i_codec, 0 );
1719 if( p_stream->fmt.i_codec ==
1720 VLC_FOURCC('u','n','d','f') )
1722 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1723 ( i_format_tag >> 8 ) & 0xff,
1724 i_format_tag & 0xff );
1727 msg_Dbg( p_demux, "found audio header of type: %.4s",
1728 (char *)&p_stream->fmt.i_codec );
1729 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1730 "%dbits/sample %dkb/s",
1732 p_stream->fmt.audio.i_channels,
1733 p_stream->fmt.audio.i_rate,
1734 p_stream->fmt.audio.i_bitspersample,
1735 p_stream->fmt.i_bitrate / 1024 );
1737 /* Check for text (subtitles) header */
1738 else if( !strncmp(st->streamtype, "text", 4) )
1740 /* We need to get rid of the header packet */
1741 ogg_stream_packetout( &p_stream->os, &oggpacket );
1743 msg_Dbg( p_demux, "found text subtitle header" );
1744 p_stream->fmt.i_cat = SPU_ES;
1745 p_stream->fmt.i_codec = VLC_CODEC_SUBT;
1746 p_stream->f_rate = 1000; /* granulepos is in millisec */
1750 msg_Dbg( p_demux, "stream %d has a header marker "
1751 "but is of an unknown type", p_ogg->i_streams-1 );
1756 else if( oggpacket.bytes >= 8 &&
1757 ! memcmp( oggpacket.packet, "fishead\0", 8 ) )
1761 msg_Dbg( p_demux, "stream %d is a skeleton",
1762 p_ogg->i_streams-1 );
1763 Ogg_ReadSkeletonHeader( p_demux, p_stream, &oggpacket );
1767 msg_Dbg( p_demux, "stream %d is of unknown type",
1768 p_ogg->i_streams-1 );
1773 /* we'll need to get all headers */
1774 p_ogg->pp_stream[i_stream]->b_initializing |= p_ogg->pp_stream[i_stream]->b_force_backup;
1776 if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS )
1777 return VLC_EGENERIC;
1780 /* This is the first data page, which means we are now finished
1781 * with the initial pages. We just need to store it in the relevant
1783 for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1785 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
1786 &p_ogg->current_page ) == 0 )
1788 p_ogg->b_page_waiting = true;
1797 return VLC_EGENERIC;
1800 /****************************************************************************
1801 * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
1802 * Elementary streams.
1803 ****************************************************************************/
1804 static int Ogg_BeginningOfStream( demux_t *p_demux )
1806 demux_sys_t *p_ogg = p_demux->p_sys ;
1807 logical_stream_t *p_old_stream = p_ogg->p_old_stream;
1810 /* Find the logical streams embedded in the physical stream and
1811 * initialize our p_ogg structure. */
1812 if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS )
1814 msg_Warn( p_demux, "couldn't find any ogg logical stream" );
1815 return VLC_EGENERIC;
1818 p_ogg->i_bitrate = 0;
1820 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1822 logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
1824 p_stream->p_es = NULL;
1826 /* initialise kframe index */
1829 /* Try first to reuse an old ES */
1831 p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
1832 p_old_stream->fmt.i_codec == p_stream->fmt.i_codec )
1834 msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
1836 p_stream->p_es = p_old_stream->p_es;
1837 es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
1839 p_old_stream->p_es = NULL;
1840 p_old_stream = NULL;
1843 if( !p_stream->p_es )
1845 /* Better be safe than sorry when possible with ogm */
1846 if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
1847 p_stream->fmt.i_codec == VLC_CODEC_A52 )
1848 p_stream->fmt.b_packetized = false;
1850 p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
1853 // TODO: something to do here ?
1854 if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
1856 /* Set the CMML stream active */
1857 es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
1860 if ( p_stream->fmt.i_bitrate == 0 &&
1861 ( p_stream->fmt.i_cat == VIDEO_ES ||
1862 p_stream->fmt.i_cat == AUDIO_ES ) )
1863 p_ogg->b_partial_bitrate = true;
1865 p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
1867 p_stream->i_pcr = p_stream->i_previous_pcr =
1868 p_stream->i_interpolated_pcr = -1;
1869 p_stream->b_reinit = false;
1872 if( p_ogg->p_old_stream )
1874 if( p_ogg->p_old_stream->p_es )
1875 msg_Dbg( p_demux, "old stream not reused" );
1876 Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
1877 p_ogg->p_old_stream = NULL;
1881 /* get total frame count for video stream; we will need this for seeking */
1882 p_ogg->i_total_frames = 0;
1887 /****************************************************************************
1888 * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
1889 ****************************************************************************/
1890 static void Ogg_EndOfStream( demux_t *p_demux )
1892 demux_sys_t *p_ogg = p_demux->p_sys ;
1895 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1896 Ogg_LogicalStreamDelete( p_demux, p_ogg->pp_stream[i_stream] );
1897 free( p_ogg->pp_stream );
1900 p_ogg->i_bitrate = 0;
1901 p_ogg->i_streams = 0;
1902 p_ogg->pp_stream = NULL;
1903 p_ogg->skeleton.major = 0;
1904 p_ogg->skeleton.minor = 0;
1908 vlc_meta_Delete( p_ogg->p_meta );
1909 p_ogg->p_meta = NULL;
1911 for ( int i=0; i < p_ogg->i_seekpoints; i++ )
1913 if ( p_ogg->pp_seekpoints[i] )
1914 vlc_seekpoint_Delete( p_ogg->pp_seekpoints[i] );
1916 TAB_CLEAN( p_ogg->i_seekpoints, p_ogg->pp_seekpoints );
1917 p_ogg->i_seekpoints = 0;
1921 * This function delete and release all data associated to a logical_stream_t
1923 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream )
1925 if( p_stream->p_es )
1926 es_out_Del( p_demux->out, p_stream->p_es );
1928 ogg_stream_clear( &p_stream->os );
1929 free( p_stream->p_headers );
1931 es_format_Clean( &p_stream->fmt_old );
1932 es_format_Clean( &p_stream->fmt );
1934 if ( p_stream->idx != NULL)
1936 oggseek_index_entries_free( p_stream->idx );
1939 Ogg_FreeSkeleton( p_stream->p_skel );
1940 p_stream->p_skel = NULL;
1941 if ( p_demux->p_sys->p_skelstream == p_stream )
1942 p_demux->p_sys->p_skelstream = NULL;
1947 * This function check if a we need to reset a decoder in case we are
1950 static bool Ogg_IsVorbisFormatCompatible( const es_format_t *p_new, const es_format_t *p_old )
1952 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
1953 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
1954 unsigned i_new_count;
1955 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
1958 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
1959 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
1960 unsigned i_old_count;
1961 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
1964 bool b_match = i_new_count == i_old_count;
1965 for( unsigned i = 0; i < i_new_count && b_match; i++ )
1967 /* Ignore vorbis comment */
1970 if( pi_new_size[i] != pi_old_size[i] ||
1971 memcmp( pp_new_data[i], pp_old_data[i], pi_new_size[i] ) )
1978 static bool Ogg_IsOpusFormatCompatible( const es_format_t *p_new,
1979 const es_format_t *p_old )
1981 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
1982 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
1983 unsigned i_new_count;
1984 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
1986 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
1987 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
1988 unsigned i_old_count;
1989 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
1991 bool b_match = false;
1992 if( i_new_count == i_old_count && i_new_count > 0 )
1994 static const unsigned char default_map[2] = { 0, 1 };
1995 unsigned char *p_old_head;
1996 unsigned char *p_new_head;
1997 const unsigned char *p_old_map;
1998 const unsigned char *p_new_map;
1999 int i_old_channel_count;
2000 int i_new_channel_count;
2001 int i_old_stream_count;
2002 int i_new_stream_count;
2003 int i_old_coupled_count;
2004 int i_new_coupled_count;
2005 p_old_head = (unsigned char *)pp_old_data[0];
2006 i_old_channel_count = i_old_stream_count = i_old_coupled_count = 0;
2007 p_old_map = default_map;
2008 if( pi_old_size[0] >= 19 && p_old_head[8] <= 15 )
2010 i_old_channel_count = p_old_head[9];
2011 switch( p_old_head[18] )
2014 i_old_stream_count = 1;
2015 i_old_coupled_count = i_old_channel_count - 1;
2018 if( pi_old_size[0] >= 21U + i_old_channel_count )
2020 i_old_stream_count = p_old_head[19];
2021 i_old_coupled_count = p_old_head[20];
2022 p_old_map = p_old_head + 21;
2027 p_new_head = (unsigned char *)pp_new_data[0];
2028 i_new_channel_count = i_new_stream_count = i_new_coupled_count = 0;
2029 p_new_map = default_map;
2030 if( pi_new_size[0] >= 19 && p_new_head[8] <= 15 )
2032 i_new_channel_count = p_new_head[9];
2033 switch( p_new_head[18] )
2036 i_new_stream_count = 1;
2037 i_new_coupled_count = i_new_channel_count - 1;
2040 if( pi_new_size[0] >= 21U + i_new_channel_count )
2042 i_new_stream_count = p_new_head[19];
2043 i_new_coupled_count = p_new_head[20];
2044 p_new_map = p_new_head+21;
2049 b_match = i_old_channel_count == i_new_channel_count &&
2050 i_old_stream_count == i_new_stream_count &&
2051 i_old_coupled_count == i_new_coupled_count &&
2052 memcmp(p_old_map, p_new_map,
2053 i_new_channel_count*sizeof(*p_new_map)) == 0;
2059 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream )
2061 bool b_compatible = false;
2062 if( !p_stream->fmt_old.i_cat || !p_stream->fmt_old.i_codec )
2065 /* Only Vorbis and Opus are supported. */
2066 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2067 b_compatible = Ogg_IsVorbisFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2068 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
2069 b_compatible = Ogg_IsOpusFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2072 msg_Warn( p_demux, "cannot reuse old stream, resetting the decoder" );
2074 return !b_compatible;
2076 static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
2077 const void *p_headers, unsigned i_headers, unsigned i_skip )
2079 demux_sys_t *p_ogg = p_demux->p_sys;
2081 unsigned pi_size[XIPH_MAX_HEADER_COUNT];
2082 void *pp_data[XIPH_MAX_HEADER_COUNT];
2084 if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
2087 /* TODO how to handle multiple comments properly ? */
2088 if( i_count >= 2 && pi_size[1] > i_skip )
2090 int i_cover_score = 0;
2091 int i_cover_idx = 0;
2092 float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
2093 float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
2094 for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
2096 pf_replay_gain[i] = 0;
2097 pf_replay_peak[i] = 0;
2099 vorbis_ParseComment( &p_ogg->p_meta, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip,
2100 &p_ogg->i_attachments, &p_ogg->attachments,
2101 &i_cover_score, &i_cover_idx,
2102 &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
2103 &pf_replay_gain, &pf_replay_peak );
2104 if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
2107 snprintf( psz_url, sizeof(psz_url), "attachment://%s",
2108 p_ogg->attachments[i_cover_idx]->psz_name );
2109 vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
2112 for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
2114 if ( pf_replay_gain[i] != 0 )
2116 p_fmt->audio_replay_gain.pb_gain[i] = true;
2117 p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
2118 msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
2120 if ( pf_replay_peak[i] != 0 )
2122 p_fmt->audio_replay_gain.pb_peak[i] = true;
2123 p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
2124 msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
2129 if( p_ogg->i_seekpoints > 1 )
2131 p_demux->info.i_update |= INPUT_UPDATE_TITLE_LIST;
2134 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers )
2136 demux_sys_t *p_ogg = p_demux->p_sys;
2138 switch( p_fmt->i_codec )
2140 /* 3 headers with the 2° one being the comments */
2141 case VLC_CODEC_VORBIS:
2142 case VLC_CODEC_THEORA:
2143 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+6 );
2145 case VLC_CODEC_OPUS:
2146 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 8 );
2148 case VLC_CODEC_SPEEX:
2149 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
2152 /* N headers with the 2° one being the comments */
2153 case VLC_CODEC_KATE:
2154 /* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
2155 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+7+1 );
2159 case VLC_CODEC_FLAC:
2160 msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&p_fmt->i_codec );
2164 case VLC_CODEC_CMML: /* CMML is XML text, doesn't have Vorbis comments */
2165 case VLC_CODEC_DIRAC:
2170 p_demux->info.i_update |= INPUT_UPDATE_META;
2173 static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
2174 ogg_packet *p_oggpacket )
2177 int i_fps_numerator;
2178 int i_fps_denominator;
2179 int i_keyframe_frequency_force;
2185 p_stream->fmt.i_cat = VIDEO_ES;
2186 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2188 /* Signal that we want to keep a backup of the theora
2189 * stream headers. They will be used when switching between
2191 p_stream->b_force_backup = true;
2193 /* Cheat and get additionnal info ;) */
2194 bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
2195 bs_skip( &bitstream, 56 );
2197 i_major = bs_read( &bitstream, 8 ); /* major version num */
2198 i_minor = bs_read( &bitstream, 8 ); /* minor version num */
2199 i_subminor = bs_read( &bitstream, 8 ); /* subminor version num */
2201 bs_read( &bitstream, 16 ) /*<< 4*/; /* width */
2202 bs_read( &bitstream, 16 ) /*<< 4*/; /* height */
2203 bs_read( &bitstream, 24 ); /* frame width */
2204 bs_read( &bitstream, 24 ); /* frame height */
2205 bs_read( &bitstream, 8 ); /* x offset */
2206 bs_read( &bitstream, 8 ); /* y offset */
2208 i_fps_numerator = bs_read( &bitstream, 32 );
2209 i_fps_denominator = bs_read( &bitstream, 32 );
2210 i_fps_denominator = __MAX( i_fps_denominator, 1 );
2211 bs_read( &bitstream, 24 ); /* aspect_numerator */
2212 bs_read( &bitstream, 24 ); /* aspect_denominator */
2214 p_stream->fmt.video.i_frame_rate = i_fps_numerator;
2215 p_stream->fmt.video.i_frame_rate_base = i_fps_denominator;
2217 bs_read( &bitstream, 8 ); /* colorspace */
2218 p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
2219 bs_read( &bitstream, 6 ); /* quality */
2221 i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 );
2223 /* granule_shift = i_log( frequency_force -1 ) */
2224 p_stream->i_granule_shift = 0;
2225 i_keyframe_frequency_force--;
2226 while( i_keyframe_frequency_force )
2228 p_stream->i_granule_shift++;
2229 i_keyframe_frequency_force >>= 1;
2232 i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2233 p_stream->i_keyframe_offset = 0;
2234 p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
2236 if ( i_version >= 3002001 )
2238 p_stream->i_keyframe_offset = 1;
2242 static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
2243 ogg_packet *p_oggpacket )
2247 p_stream->fmt.i_cat = AUDIO_ES;
2248 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2250 /* Signal that we want to keep a backup of the vorbis
2251 * stream headers. They will be used when switching between
2253 p_stream->b_force_backup = true;
2255 /* Cheat and get additionnal info ;) */
2256 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2257 oggpack_adv( &opb, 88 );
2258 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2259 fill_channels_info(&p_stream->fmt.audio);
2260 p_stream->f_rate = p_stream->fmt.audio.i_rate =
2261 oggpack_read( &opb, 32 );
2262 oggpack_adv( &opb, 32 );
2263 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2266 static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
2267 ogg_packet *p_oggpacket )
2271 p_stream->fmt.i_cat = AUDIO_ES;
2272 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2274 /* Signal that we want to keep a backup of the speex
2275 * stream headers. They will be used when switching between
2277 p_stream->b_force_backup = true;
2279 /* Cheat and get additionnal info ;) */
2280 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2281 oggpack_adv( &opb, 224 );
2282 oggpack_adv( &opb, 32 ); /* speex_version_id */
2283 oggpack_adv( &opb, 32 ); /* header_size */
2284 p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
2285 oggpack_adv( &opb, 32 ); /* mode */
2286 oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
2287 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
2288 fill_channels_info(&p_stream->fmt.audio);
2289 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2290 oggpack_adv( &opb, 32 ); /* frame_size */
2291 oggpack_adv( &opb, 32 ); /* vbr */
2292 oggpack_adv( &opb, 32 ); /* frames_per_packet */
2293 p_stream->i_extra_headers_packets = oggpack_read( &opb, 32 ); /* extra_headers */
2296 static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
2297 ogg_packet *p_oggpacket )
2301 p_stream->fmt.i_cat = AUDIO_ES;
2302 p_stream->fmt.i_codec = VLC_CODEC_OPUS;
2304 /* Signal that we want to keep a backup of the opus
2305 * stream headers. They will be used when switching between
2307 p_stream->b_force_backup = true;
2309 /* All OggOpus streams are timestamped at 48kHz and
2310 * can be played at 48kHz. */
2311 p_stream->f_rate = p_stream->fmt.audio.i_rate = 48000;
2312 p_stream->fmt.i_bitrate = 0;
2314 /* Cheat and get additional info ;) */
2315 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2316 oggpack_adv( &opb, 64 );
2317 oggpack_adv( &opb, 8 ); /* version_id */
2318 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2319 fill_channels_info(&p_stream->fmt.audio);
2320 p_stream->i_pre_skip = oggpack_read( &opb, 16 );
2323 static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
2324 ogg_packet *p_oggpacket )
2326 /* Parse the STREAMINFO metadata */
2329 bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
2332 if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) != 0 )
2334 msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
2338 if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
2341 p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
2342 p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
2343 fill_channels_info(&p_stream->fmt.audio);
2345 msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
2346 p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
2350 msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
2353 /* Fake this as the last metadata block */
2354 *((uint8_t*)p_oggpacket->packet) |= 0x80;
2357 static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
2358 ogg_packet *p_oggpacket )
2366 p_stream->fmt.i_cat = SPU_ES;
2367 p_stream->fmt.i_codec = VLC_CODEC_KATE;
2369 /* Signal that we want to keep a backup of the kate
2370 * stream headers. They will be used when switching between
2372 p_stream->b_force_backup = true;
2374 /* Cheat and get additionnal info ;) */
2375 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2376 oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */
2377 p_stream->i_kate_num_headers = oggpack_read( &opb, 8 );
2378 oggpack_adv( &opb, 3*8 );
2379 p_stream->i_granule_shift = oggpack_read( &opb, 8 );
2380 oggpack_adv( &opb, 8*8 ); /* reserved */
2381 gnum = oggpack_read( &opb, 32 );
2382 gden = oggpack_read( &opb, 32 );
2383 p_stream->f_rate = (double)gnum/gden;
2385 p_stream->fmt.psz_language = malloc(16);
2386 if( p_stream->fmt.psz_language )
2388 for( n = 0; n < 16; n++ )
2389 p_stream->fmt.psz_language[n] = oggpack_read(&opb,8);
2390 p_stream->fmt.psz_language[15] = 0; /* just in case */
2394 for( n = 0; n < 16; n++ )
2395 oggpack_read(&opb,8);
2397 p_stream->fmt.psz_description = malloc(16);
2398 if( p_stream->fmt.psz_description )
2400 for( n = 0; n < 16; n++ )
2401 p_stream->fmt.psz_description[n] = oggpack_read(&opb,8);
2402 p_stream->fmt.psz_description[15] = 0; /* just in case */
2404 /* Now find a localized user readable description for this category */
2405 psz_desc = strdup(FindKateCategoryName(p_stream->fmt.psz_description));
2408 free( p_stream->fmt.psz_description );
2409 p_stream->fmt.psz_description = psz_desc;
2414 for( n = 0; n < 16; n++ )
2415 oggpack_read(&opb,8);
2419 static void Ogg_ApplyContentType( logical_stream_t *p_stream, const char* psz_value,
2420 bool *b_force_backup, bool *b_packet_out )
2422 if( !strncmp(psz_value, "audio/x-wav", 11) )
2424 /* n.b. WAVs are unsupported right now */
2425 p_stream->fmt.i_cat = UNKNOWN_ES;
2426 free( p_stream->fmt.psz_description );
2427 p_stream->fmt.psz_description = strdup("WAV Audio (Unsupported)");
2429 else if( !strncmp(psz_value, "audio/x-vorbis", 14) ||
2430 !strncmp(psz_value, "audio/vorbis", 12) )
2432 p_stream->fmt.i_cat = AUDIO_ES;
2433 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2435 *b_force_backup = true;
2437 else if( !strncmp(psz_value, "audio/x-speex", 13) ||
2438 !strncmp(psz_value, "audio/speex", 11) )
2440 p_stream->fmt.i_cat = AUDIO_ES;
2441 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2443 *b_force_backup = true;
2445 else if( !strncmp(psz_value, "audio/flac", 10) )
2447 p_stream->fmt.i_cat = AUDIO_ES;
2448 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
2450 *b_force_backup = true;
2452 else if( !strncmp(psz_value, "video/x-theora", 14) ||
2453 !strncmp(psz_value, "video/theora", 12) )
2455 p_stream->fmt.i_cat = VIDEO_ES;
2456 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2458 *b_force_backup = true;
2460 else if( !strncmp(psz_value, "video/x-xvid", 12) )
2462 p_stream->fmt.i_cat = VIDEO_ES;
2463 p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' );
2465 *b_force_backup = true;
2467 else if( !strncmp(psz_value, "video/mpeg", 10) )
2469 /* n.b. MPEG streams are unsupported right now */
2470 p_stream->fmt.i_cat = VIDEO_ES;
2471 p_stream->fmt.i_codec = VLC_CODEC_MPGV;
2473 else if( !strncmp(psz_value, "text/x-cmml", 11) ||
2474 !strncmp(psz_value, "text/cmml", 9) )
2476 p_stream->fmt.i_cat = SPU_ES;
2477 p_stream->fmt.i_codec = VLC_CODEC_CMML;
2478 *b_packet_out = true;
2480 else if( !strncmp(psz_value, "application/kate", 16) )
2483 p_stream->fmt.i_cat = UNKNOWN_ES;
2484 free( p_stream->fmt.psz_description );
2485 p_stream->fmt.psz_description = strdup("OGG Kate Overlay (Unsupported)");
2489 static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
2490 logical_stream_t *p_stream,
2491 ogg_packet *p_oggpacket )
2493 if( p_oggpacket->bytes >= 28 &&
2494 !memcmp( p_oggpacket->packet, "Annodex", 7 ) )
2498 uint16_t major_version;
2499 uint16_t minor_version;
2500 uint64_t timebase_numerator;
2501 uint64_t timebase_denominator;
2503 Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
2505 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2506 oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
2507 major_version = oggpack_read( &opb, 2*8 ); /* major version */
2508 minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
2509 timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
2510 timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
2512 msg_Dbg( p_demux, "Annodex info: version %"PRIu16".%"PRIu16" "
2513 "Timebase %"PRId64" / %"PRId64,
2514 major_version, minor_version,
2515 timebase_numerator, timebase_denominator );
2517 else if( p_oggpacket->bytes >= 42 &&
2518 !memcmp( p_oggpacket->packet, "AnxData", 7 ) )
2520 uint64_t granule_rate_numerator;
2521 uint64_t granule_rate_denominator;
2522 char content_type_string[1024];
2524 /* Read in Annodex header fields */
2526 granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
2527 granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
2528 p_stream->i_secondary_header_packets =
2529 GetDWLE( &p_oggpacket->packet[24] );
2531 /* we are guaranteed that the first header field will be
2532 * the content-type (by the Annodex standard) */
2533 content_type_string[0] = '\0';
2534 if( !strncasecmp( (char*)(&p_oggpacket->packet[28]), "Content-Type: ", 14 ) )
2536 uint8_t *p = memchr( &p_oggpacket->packet[42], '\r',
2537 p_oggpacket->bytes - 1 );
2538 if( p && p[0] == '\r' && p[1] == '\n' )
2539 sscanf( (char*)(&p_oggpacket->packet[42]), "%1023s\r\n",
2540 content_type_string );
2543 msg_Dbg( p_demux, "AnxData packet info: %"PRId64" / %"PRId64", %d, ``%s''",
2544 granule_rate_numerator, granule_rate_denominator,
2545 p_stream->i_secondary_header_packets, content_type_string );
2547 p_stream->f_rate = (float) granule_rate_numerator /
2548 (float) granule_rate_denominator;
2550 /* What type of file do we have?
2551 * strcmp is safe to use here because we've extracted
2552 * content_type_string from the stream manually */
2553 bool b_dopacketout = false;
2554 Ogg_ApplyContentType( p_stream, content_type_string,
2555 &p_stream->b_force_backup, &b_dopacketout );
2556 if ( b_dopacketout ) ogg_stream_packetout( &p_stream->os, p_oggpacket );
2560 static void Ogg_ReadSkeletonHeader( demux_t *p_demux, logical_stream_t *p_stream,
2561 ogg_packet *p_oggpacket )
2563 p_demux->p_sys->p_skelstream = p_stream;
2564 /* There can be only 1 skeleton for streams */
2565 p_demux->p_sys->skeleton.major = GetWLE( &p_oggpacket->packet[8] );
2566 p_demux->p_sys->skeleton.minor = GetWLE( &p_oggpacket->packet[10] );
2567 if ( asprintf( & p_stream->fmt.psz_description,
2568 "OGG Skeleton version %" PRIu16 ".%" PRIu16,
2569 p_demux->p_sys->skeleton.major,
2570 p_demux->p_sys->skeleton.minor ) < 0 )
2571 p_stream->fmt.psz_description = NULL;
2574 static void Ogg_ReadSkeletonBones( demux_t *p_demux, ogg_packet *p_oggpacket )
2576 if ( p_demux->p_sys->skeleton.major < 3 || p_oggpacket->bytes < 52 ) return;
2578 /* Find the matching stream for this skeleton data */
2579 ogg_int32_t i_serialno = GetDWLE( &p_oggpacket->packet[12] );
2580 logical_stream_t *p_target_stream = NULL;
2581 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
2583 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
2585 p_target_stream = p_demux->p_sys->pp_stream[i];
2589 if ( !p_target_stream ) return;
2591 ogg_skeleton_t *p_skel = p_target_stream->p_skel;
2594 p_skel = malloc( sizeof( ogg_skeleton_t ) );
2595 if ( !p_skel ) return;
2596 TAB_INIT( p_skel->i_messages, p_skel->ppsz_messages );
2597 p_skel->p_index = NULL;
2598 p_target_stream->p_skel = p_skel;
2601 const unsigned char *p_messages = p_oggpacket->packet + 8 + GetDWLE( &p_oggpacket->packet[8] );
2602 const unsigned char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
2603 const unsigned char *p = p_messages;
2604 while ( p <= p_boundary - 1 && p > p_oggpacket->packet )
2606 if ( *p == 0x0D && *(p+1) == 0x0A )
2608 char *psz_message = strndup( (const char *) p_messages,
2612 msg_Dbg( p_demux, "stream %" PRId32 " [%s]", i_serialno, psz_message );
2613 TAB_APPEND( p_skel->i_messages, p_skel->ppsz_messages, psz_message );
2615 if ( p < p_boundary - 1 ) p_messages = p + 2;
2622 /* Unpacks the 7bit variable encoding used in skeleton indexes */
2623 unsigned const char * Read7BitsVariableLE( unsigned const char *p_begin,
2624 unsigned const char *p_end,
2625 uint64_t *pi_value )
2631 while ( p_begin < p_end )
2633 i_read = *p_begin & 0x7F; /* High bit is start of integer */
2634 *pi_value = *pi_value | ( i_read << i_shift );
2636 if ( (*p_begin++ & 0x80) == 0x80 ) break; /* see prev */
2639 *pi_value = GetQWLE( pi_value );
2643 static void Ogg_ReadSkeletonIndex( demux_t *p_demux, ogg_packet *p_oggpacket )
2645 if ( p_demux->p_sys->skeleton.major < 4
2646 || p_oggpacket->bytes < 44 /* Need at least 1 index value (42+1+1) */
2649 /* Find the matching stream for this skeleton data */
2650 int32_t i_serialno = GetDWLE( &p_oggpacket->packet[6] );
2651 logical_stream_t *p_stream = NULL;
2652 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
2654 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
2656 p_stream = p_demux->p_sys->pp_stream[i];
2660 if ( !p_stream ) return;
2661 uint64_t i_keypoints = GetQWLE( &p_oggpacket->packet[10] );
2662 msg_Dbg( p_demux, "%" PRIi64 " index data for %" PRIi32, i_keypoints, i_serialno );
2663 if ( !i_keypoints ) return;
2665 p_stream->p_skel->i_indexstampden = GetQWLE( &p_oggpacket->packet[18] );
2666 p_stream->p_skel->i_indexfirstnum = GetQWLE( &p_oggpacket->packet[24] );
2667 p_stream->p_skel->i_indexlastnum = GetQWLE( &p_oggpacket->packet[32] );
2668 unsigned const char *p_fwdbyte = &p_oggpacket->packet[42];
2669 unsigned const char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
2670 uint64_t i_offset = 0;
2671 uint64_t i_time = 0;
2672 uint64_t i_keypoints_found = 0;
2674 while( p_fwdbyte < p_boundary && i_keypoints_found < i_keypoints )
2677 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
2679 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
2680 i_time += i_val * p_stream->p_skel->i_indexstampden;
2681 i_keypoints_found++;
2684 if ( i_keypoints_found != i_keypoints )
2686 msg_Warn( p_demux, "Invalid Index: missing entries" );
2690 p_stream->p_skel->p_index = malloc( p_oggpacket->bytes - 42 );
2691 if ( !p_stream->p_skel->p_index ) return;
2692 memcpy( p_stream->p_skel->p_index, &p_oggpacket->packet[42],
2693 p_oggpacket->bytes - 42 );
2694 p_stream->p_skel->i_index = i_keypoints_found;
2695 p_stream->p_skel->i_index_size = p_oggpacket->bytes - 42;
2698 static void Ogg_FreeSkeleton( ogg_skeleton_t *p_skel )
2700 if ( !p_skel ) return;
2701 for ( int i=0; i< p_skel->i_messages; i++ )
2702 free( p_skel->ppsz_messages[i] );
2703 TAB_CLEAN( p_skel->i_messages, p_skel->ppsz_messages );
2704 free( p_skel->p_index );
2708 static void Ogg_ApplySkeleton( logical_stream_t *p_stream )
2710 if ( !p_stream->p_skel ) return;
2711 for ( int i=0; i< p_stream->p_skel->i_messages; i++ )
2713 const char *psz_message = p_stream->p_skel->ppsz_messages[i];
2714 if ( ! strncmp( "Name: ", psz_message, 6 ) )
2716 free( p_stream->fmt.psz_description );
2717 p_stream->fmt.psz_description = strdup( psz_message + 6 );
2719 else if ( ! strncmp("Content-Type: ", psz_message, 14 ) )
2722 Ogg_ApplyContentType( p_stream, psz_message + 14, &b_foo, &b_foo );
2727 /* Return true if there's a skeleton exact match */
2728 bool Ogg_GetBoundsUsingSkeletonIndex( logical_stream_t *p_stream, int64_t i_time,
2729 int64_t *pi_lower, int64_t *pi_upper )
2731 if ( !p_stream || !p_stream->p_skel || !p_stream->p_skel->p_index )
2734 /* Validate range */
2735 if ( i_time < p_stream->p_skel->i_indexfirstnum
2736 * p_stream->p_skel->i_indexstampden ||
2737 i_time > p_stream->p_skel->i_indexlastnum
2738 * p_stream->p_skel->i_indexstampden ) return false;
2740 /* Then Lookup its index */
2741 unsigned const char *p_fwdbyte = p_stream->p_skel->p_index;
2746 } current = { 0, 0 }, prev = { -1, -1 };
2748 uint64_t i_keypoints_found = 0;
2750 while( p_fwdbyte < p_fwdbyte + p_stream->p_skel->i_index_size
2751 && i_keypoints_found < p_stream->p_skel->i_index )
2754 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
2755 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
2756 current.i_pos += i_val;
2757 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
2758 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
2759 current.i_time += i_val * p_stream->p_skel->i_indexstampden;
2760 if ( current.i_pos < 0 || current.i_time < 0 ) break;
2762 i_keypoints_found++;
2764 if ( i_time <= current.i_time )
2766 *pi_lower = prev.i_pos;
2767 *pi_upper = current.i_pos;
2768 return ( i_time == current.i_time );
2775 static uint32_t dirac_uint( bs_t *p_bs )
2777 uint32_t u_count = 0, u_value = 0;
2779 while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
2783 u_value |= bs_read( p_bs, 1 );
2786 return (1<<u_count) - 1 + u_value;
2789 static int dirac_bool( bs_t *p_bs )
2791 return bs_read( p_bs, 1 );
2794 static bool Ogg_ReadDiracHeader( logical_stream_t *p_stream,
2795 ogg_packet *p_oggpacket )
2797 static const struct {
2798 uint32_t u_n /* numerator */, u_d /* denominator */;
2799 } p_dirac_frate_tbl[] = { /* table 10.3 */
2800 {1,1}, /* this first value is never used */
2801 {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
2802 {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
2804 static const size_t u_dirac_frate_tbl = sizeof(p_dirac_frate_tbl)/sizeof(*p_dirac_frate_tbl);
2806 static const uint32_t pu_dirac_vidfmt_frate[] = { /* table C.1 */
2807 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
2809 static const size_t u_dirac_vidfmt_frate = sizeof(pu_dirac_vidfmt_frate)/sizeof(*pu_dirac_vidfmt_frate);
2813 p_stream->i_granule_shift = 22; /* not 32 */
2815 /* Backing up stream headers is not required -- seqhdrs are repeated
2816 * thoughout the stream at suitable decoding start points */
2817 p_stream->b_force_backup = false;
2819 /* read in useful bits from sequence header */
2820 bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes );
2821 bs_skip( &bs, 13*8); /* parse_info_header */
2822 dirac_uint( &bs ); /* major_version */
2823 dirac_uint( &bs ); /* minor_version */
2824 dirac_uint( &bs ); /* profile */
2825 dirac_uint( &bs ); /* level */
2827 uint32_t u_video_format = dirac_uint( &bs ); /* index */
2828 if( u_video_format >= u_dirac_vidfmt_frate )
2830 /* don't know how to parse this ogg dirac stream */
2834 if( dirac_bool( &bs ) )
2836 dirac_uint( &bs ); /* frame_width */
2837 dirac_uint( &bs ); /* frame_height */
2840 if( dirac_bool( &bs ) )
2842 dirac_uint( &bs ); /* chroma_format */
2845 if( dirac_bool( &bs ) )
2847 dirac_uint( &bs ); /* scan_format */
2850 uint32_t u_n = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_n;
2851 uint32_t u_d = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_d;
2852 if( dirac_bool( &bs ) )
2854 uint32_t u_frame_rate_index = dirac_uint( &bs );
2855 if( u_frame_rate_index >= u_dirac_frate_tbl )
2857 /* something is wrong with this stream */
2860 u_n = p_dirac_frate_tbl[u_frame_rate_index].u_n;
2861 u_d = p_dirac_frate_tbl[u_frame_rate_index].u_d;
2862 if( u_frame_rate_index == 0 )
2864 u_n = dirac_uint( &bs ); /* frame_rate_numerator */
2865 u_d = dirac_uint( &bs ); /* frame_rate_denominator */
2868 p_stream->f_rate = (float) u_n / u_d;
2870 /* probably is an ogg dirac es */
2871 p_stream->fmt.i_cat = VIDEO_ES;
2872 p_stream->fmt.i_codec = VLC_CODEC_DIRAC;