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 ( demux_t *, 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 void Ogg_CreateES( demux_t *p_demux );
120 static int Ogg_BeginningOfStream( demux_t *p_demux );
121 static int Ogg_FindLogicalStreams( demux_t *p_demux );
122 static void Ogg_EndOfStream( demux_t *p_demux );
125 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream );
126 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream );
129 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers );
131 /* Logical bitstream headers */
132 static void Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * );
133 static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
134 static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
135 static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * );
136 static void Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
137 static void Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );
138 static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
139 static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
140 static void Ogg_ReadSkeletonHeader( demux_t *, logical_stream_t *, ogg_packet * );
143 static void Ogg_ReadSkeletonBones( demux_t *, ogg_packet * );
144 static void Ogg_ReadSkeletonIndex( demux_t *, ogg_packet * );
145 static void Ogg_FreeSkeleton( ogg_skeleton_t * );
146 static void Ogg_ApplySkeleton( logical_stream_t * );
148 static void fill_channels_info(audio_format_t *audio)
150 static const int pi_channels_map[9] =
154 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
155 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
156 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
157 | AOUT_CHAN_REARRIGHT,
158 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
159 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
160 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
161 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
162 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
163 | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
164 | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
165 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
166 | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
170 unsigned chans = audio->i_channels;
171 if (chans < sizeof(pi_channels_map) / sizeof(pi_channels_map[0]))
172 audio->i_physical_channels =
173 audio->i_original_channels = pi_channels_map[chans];
176 /*****************************************************************************
177 * Open: initializes ogg demux structures
178 *****************************************************************************/
179 static int Open( vlc_object_t * p_this )
181 demux_t *p_demux = (demux_t *)p_this;
183 const uint8_t *p_peek;
185 /* Check if we are dealing with an ogg stream */
186 if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
187 if( !p_demux->b_force && memcmp( p_peek, "OggS", 4 ) )
193 p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
197 p_sys->i_length = -1;
198 p_sys->b_preparsing_done = false;
200 /* Set exported functions */
201 p_demux->pf_demux = Demux;
202 p_demux->pf_control = Control;
204 /* Initialize the Ogg physical bitstream parser */
205 ogg_sync_init( &p_sys->oy );
208 TAB_INIT( p_sys->i_seekpoints, p_sys->pp_seekpoints );
211 while ( !p_sys->b_preparsing_done && p_demux->pf_demux( p_demux ) > 0 )
217 /*****************************************************************************
218 * Close: frees unused data
219 *****************************************************************************/
220 static void Close( vlc_object_t *p_this )
222 demux_t *p_demux = (demux_t *)p_this;
223 demux_sys_t *p_sys = p_demux->p_sys ;
225 /* Cleanup the bitstream parser */
226 ogg_sync_clear( &p_sys->oy );
228 Ogg_EndOfStream( p_demux );
230 if( p_sys->p_old_stream )
231 Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
236 /*****************************************************************************
237 * Demux: reads and demuxes data packets
238 *****************************************************************************
239 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
240 *****************************************************************************/
241 static int Demux( demux_t * p_demux )
243 demux_sys_t *p_sys = p_demux->p_sys;
244 ogg_packet oggpacket;
246 bool b_skipping = false;
249 int i_active_streams = p_sys->i_streams;
250 for ( int i=0; i < p_sys->i_streams; i++ )
252 if ( p_sys->pp_stream[i]->b_finished )
256 if ( i_active_streams == 0 )
258 if ( p_sys->i_streams ) /* All finished */
260 msg_Dbg( p_demux, "end of a group of logical streams" );
261 /* We keep the ES to try reusing it in Ogg_BeginningOfStream
262 * only 1 ES is supported (common case for ogg web radio) */
263 if( p_sys->i_streams == 1 )
265 p_sys->p_old_stream = p_sys->pp_stream[0];
266 TAB_CLEAN( p_sys->i_streams, p_sys->pp_stream );
268 Ogg_EndOfStream( p_demux );
269 p_sys->b_chained_boundary = true;
272 if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS )
275 msg_Dbg( p_demux, "beginning of a group of logical streams" );
277 if ( !p_sys->b_chained_boundary )
279 /* Find the real duration */
280 stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
282 Oggseek_ProbeEnd( p_demux );
283 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 );
287 es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
288 p_sys->b_chained_boundary = false;
292 if ( p_sys->b_preparsing_done )
294 for ( int i=0; i < p_sys->i_streams; i++ )
296 if ( !p_sys->pp_stream[i]->p_es )
298 Ogg_CreateES( p_demux );
305 * The first data page of a physical stream is stored in the relevant logical stream
306 * in Ogg_FindLogicalStreams. Therefore, we must not read a page and only update the
307 * stream it belongs to if we haven't processed this first page yet. If we do, we
308 * will only process that first page whenever we find the second page for this stream.
309 * While this is fine for Vorbis and Theora, which are continuous codecs, which means
310 * the second page will arrive real quick, this is not fine for Kate, whose second
311 * data page will typically arrive much later.
312 * This means it is now possible to seek right at the start of a stream where the last
313 * logical stream is Kate, without having to wait for the second data page to unblock
314 * the first one, which is the one that triggers the 'no more headers to backup' code.
315 * And, as we all know, seeking without having backed up all headers is bad, since the
316 * codec will fail to initialize if it's missing its headers.
318 if( !p_sys->b_page_waiting)
321 * Demux an ogg page from the stream
323 if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS )
325 /* Test for End of Stream */
326 if( ogg_page_eos( &p_sys->current_page ) )
328 /* If we delayed restarting encoders/SET_ES_FMT for more
329 * skeleton provided configuration */
330 if ( p_sys->p_skelstream )
332 if ( p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
334 msg_Dbg( p_demux, "End of Skeleton" );
335 p_sys->b_preparsing_done = true;
336 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
338 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
339 if ( p_stream->b_have_updated_format )
341 p_stream->b_have_updated_format = false;
342 if ( p_stream->p_skel ) Ogg_ApplySkeleton( p_stream );
343 if ( p_stream->p_es )
345 msg_Dbg( p_demux, "Resetting format for stream %d", i_stream );
346 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
347 p_stream->p_es, &p_stream->fmt );
354 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
356 if ( p_sys->pp_stream[i_stream]->i_serial_no == ogg_page_serialno( &p_sys->current_page ) )
358 p_sys->pp_stream[i_stream]->b_finished = true;
366 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
368 b_skipping |= p_sys->pp_stream[i_stream]->i_skip_frames;
371 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
373 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
375 /* if we've just pulled page, look for the right logical stream */
376 if( !p_sys->b_page_waiting )
378 if( p_sys->i_streams == 1 &&
379 ogg_page_serialno( &p_sys->current_page ) != p_stream->os.serialno )
381 msg_Err( p_demux, "Broken Ogg stream (serialno) mismatch" );
382 ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) );
384 p_stream->b_reinit = true;
385 p_stream->i_pcr = VLC_TS_0;
386 p_stream->i_interpolated_pcr = VLC_TS_0;
387 p_stream->i_previous_granulepos = -1;
388 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0);
391 /* Does fail if serialno differs */
392 if( ogg_stream_pagein( &p_stream->os, &p_sys->current_page ) != 0 )
399 /* clear the finished flag if pages after eos (ex: after a seek) */
400 if ( ! ogg_page_eos( &p_sys->current_page ) ) p_stream->b_finished = false;
403 if ( p_stream->fmt.i_cat == VIDEO_ES )
404 msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes",
405 ogg_page_pageno( &p_sys->current_page ),
406 ogg_page_granulepos( &p_sys->current_page ),
407 ogg_page_packets( &p_sys->current_page ),
408 ogg_page_continued(&p_sys->current_page),
409 p_sys->current_page.body_len )
412 while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
414 /* Read info from any secondary header packets, if there are any */
415 if( p_stream->i_secondary_header_packets > 0 )
417 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA &&
418 oggpacket.bytes >= 7 &&
419 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
421 Ogg_ReadTheoraHeader( p_stream, &oggpacket );
422 p_stream->i_secondary_header_packets = 0;
424 else if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS &&
425 oggpacket.bytes >= 7 &&
426 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
428 Ogg_ReadVorbisHeader( p_stream, &oggpacket );
429 p_stream->i_secondary_header_packets = 0;
431 else if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
433 p_stream->i_secondary_header_packets = 0;
436 /* update start of data pointer */
437 p_stream->i_data_start = stream_Tell( p_demux->s );
440 /* If any streams have i_skip_frames, only decode (pre-roll)
441 * for those streams, but don't skip headers */
442 if ( b_skipping && p_stream->i_skip_frames == 0
443 && p_stream->i_secondary_header_packets ) continue;
445 if( p_stream->b_reinit )
447 if ( Oggseek_PacketPCRFixup( p_stream, &p_sys->current_page,
450 DemuxDebug( msg_Dbg( p_demux, "PCR fixup for %"PRId64,
451 ogg_page_granulepos( &p_sys->current_page ) ) );
455 /* If synchro is re-initialized we need to drop all the packets
456 * until we find a new dated one. */
457 Ogg_UpdatePCR( p_demux, p_stream, &oggpacket );
460 if( p_stream->i_pcr >= 0 )
462 p_stream->b_reinit = false;
463 /* For Opus, trash the first 80 ms of decoded output as
464 well, to avoid blowing out speakers if we get unlucky.
465 Opus predicts content from prior frames, which can go
466 badly if we seek right where the stream goes from very
467 quiet to very loud. It will converge after a bit. */
468 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
470 ogg_int64_t start_time;
472 p_stream->i_skip_frames = 80*48;
473 /* Make sure we never play audio from within the
474 pre-skip at the beginning of the stream. */
476 Ogg_OpusPacketDuration( p_stream, &oggpacket );
477 start_time = p_stream->i_previous_granulepos;
480 start_time = start_time > duration ?
481 start_time - duration : 0;
483 if( p_stream->i_pre_skip > start_time )
485 p_stream->i_skip_frames +=
486 p_stream->i_pre_skip - start_time;
493 msg_Dbg(p_demux, "DEMUX DROPS PACKET (? / %d) pageno %ld granule %"PRId64,
494 ogg_page_packets( &p_sys->current_page ),
495 ogg_page_pageno( &p_sys->current_page ), oggpacket.granulepos );
498 p_stream->i_interpolated_pcr = -1;
499 p_stream->i_previous_granulepos = -1;
503 /* An Ogg/vorbis packet contains an end date granulepos */
504 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
505 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
506 p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
507 p_stream->fmt.i_codec == VLC_CODEC_FLAC )
509 if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
511 Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
515 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
516 VLC_TS_0 + p_stream->i_pcr );
522 DemuxDebug( if ( p_sys->b_seeked )
524 if ( Ogg_IsKeyFrame( p_stream, &oggpacket ) )
525 msg_Dbg(p_demux, "** DEMUX ON KEYFRAME **" );
527 ogg_int64_t iframe = ogg_page_granulepos( &p_sys->current_page ) >> p_stream->i_granule_shift;
528 ogg_int64_t pframe = ogg_page_granulepos( &p_sys->current_page ) - ( iframe << p_stream->i_granule_shift );
530 msg_Dbg(p_demux, "DEMUX PACKET (size %d) IS at iframe %"PRId64" pageno %ld pframe %"PRId64" OFFSET %"PRId64" PACKET NO %"PRId64" skipleft=%d",
531 ogg_page_packets( &p_sys->current_page ),
532 iframe, ogg_page_pageno( &p_sys->current_page ), pframe, p_sys->i_input_position, oggpacket.packetno, p_stream->i_skip_frames );
535 Ogg_DecodePacket( p_demux, p_stream, &oggpacket );
538 DemuxDebug( p_sys->b_seeked = false; )
540 if( !p_sys->b_page_waiting )
544 /* if a page was waiting, it's now processed */
545 p_sys->b_page_waiting = false;
547 p_sys->b_preparsing_done = true;
550 for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
552 logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
554 if ( p_stream->b_force_backup )
556 /* We have 1 or more streams needing more than 1 page for preparsing */
557 p_sys->b_preparsing_done = false;
560 if( p_stream->fmt.i_cat == SPU_ES )
562 if( p_stream->i_interpolated_pcr < 0 )
565 if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr )
566 p_sys->i_pcr = p_stream->i_interpolated_pcr;
569 if( p_sys->i_pcr >= 0 && ! b_skipping )
570 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
575 static void Ogg_ResetStreamHelper( demux_sys_t *p_sys )
577 for( int i = 0; i < p_sys->i_streams; i++ )
579 logical_stream_t *p_stream = p_sys->pp_stream[i];
581 /* we'll trash all the data until we find the next pcr */
582 p_stream->b_reinit = true;
583 p_stream->i_pcr = -1;
584 p_stream->i_interpolated_pcr = -1;
585 p_stream->i_previous_granulepos = -1;
586 ogg_stream_reset( &p_stream->os );
588 ogg_sync_reset( &p_sys->oy );
591 static logical_stream_t * Ogg_GetSelectedStream( demux_t *p_demux )
593 demux_sys_t *p_sys = p_demux->p_sys;
594 logical_stream_t *p_stream = NULL;
595 for( int i=0; i<p_sys->i_streams; i++ )
597 logical_stream_t *p_candidate = p_sys->pp_stream[i];
599 bool b_selected = false;
600 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
601 p_candidate->p_es, &b_selected );
602 if ( !b_selected ) continue;
604 if ( !p_stream && p_candidate->fmt.i_cat == AUDIO_ES )
606 p_stream = p_candidate;
607 continue; /* Try to find video anyway */
610 if ( p_candidate->fmt.i_cat == VIDEO_ES )
612 p_stream = p_candidate;
619 /*****************************************************************************
621 *****************************************************************************/
622 static int Control( demux_t *p_demux, int i_query, va_list args )
624 demux_sys_t *p_sys = p_demux->p_sys;
633 p_meta = (vlc_meta_t *)va_arg( args, vlc_meta_t* );
635 vlc_meta_Merge( p_meta, p_sys->p_meta );
638 case DEMUX_HAS_UNSUPPORTED_META:
639 pb_bool = (bool*)va_arg( args, bool* );
644 pi64 = (int64_t*)va_arg( args, int64_t * );
645 *pi64 = p_sys->i_pcr;
649 i64 = (int64_t)va_arg( args, int64_t );
650 logical_stream_t *p_stream = Ogg_GetSelectedStream( p_demux );
653 msg_Err( p_demux, "No selected seekable stream found" );
656 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
657 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
659 Ogg_ResetStreamHelper( p_sys );
660 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
667 case DEMUX_GET_ATTACHMENTS:
669 input_attachment_t ***ppp_attach =
670 (input_attachment_t***)va_arg( args, input_attachment_t*** );
671 int *pi_int = (int*)va_arg( args, int * );
673 if( p_sys->i_attachments <= 0 )
676 *pi_int = p_sys->i_attachments;
677 *ppp_attach = xmalloc( sizeof(input_attachment_t*) * p_sys->i_attachments );
678 for( int i = 0; i < p_sys->i_attachments; i++ )
679 (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
683 case DEMUX_GET_POSITION:
684 pf = (double*)va_arg( args, double * );
685 if( p_sys->i_length > 0 )
687 *pf = (double) p_sys->i_pcr /
688 (double) ( p_sys->i_length * (mtime_t)1000000 );
690 else if( stream_Size( p_demux->s ) > 0 )
692 i64 = stream_Tell( p_demux->s );
693 *pf = (double) i64 / stream_Size( p_demux->s );
698 case DEMUX_SET_POSITION:
699 /* forbid seeking if we haven't initialized all logical bitstreams yet;
700 if we allowed, some headers would not get backed up and decoder init
701 would fail, making that logical stream unusable */
702 for ( int i=0; i< p_sys->i_streams; i++ )
704 if ( p_sys->pp_stream[i]->b_initializing )
708 p_stream = Ogg_GetSelectedStream( p_demux );
711 msg_Err( p_demux, "No selected seekable stream found" );
715 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
717 f = (double)va_arg( args, double );
718 if ( p_sys->i_length <= 0 || !b /* || ! ACCESS_CAN_FASTSEEK */ )
720 Ogg_ResetStreamHelper( p_sys );
721 Oggseek_BlindSeektoPosition( p_demux, p_stream, f, b );
725 assert( p_sys->i_length > 0 );
726 i64 = CLOCK_FREQ * p_sys->i_length * f;
727 Ogg_ResetStreamHelper( p_sys );
728 if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, i64 ) >= 0 )
730 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
737 case DEMUX_GET_LENGTH:
738 if ( p_sys->i_length < 0 )
739 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
741 pi64 = (int64_t*)va_arg( args, int64_t * );
742 *pi64 = p_sys->i_length * 1000000;
745 case DEMUX_GET_TITLE_INFO:
747 input_title_t ***ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
748 int *pi_int = (int*)va_arg( args, int* );
749 int *pi_title_offset = (int*)va_arg( args, int* );
750 int *pi_seekpoint_offset = (int*)va_arg( args, int* );
752 if( p_sys->i_seekpoints > 0 )
755 *ppp_title = malloc( sizeof( input_title_t* ) );
756 input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
757 for( int i = 0; i < p_sys->i_seekpoints; i++ )
759 seekpoint_t *p_seekpoint_copy = vlc_seekpoint_Duplicate( p_sys->pp_seekpoints[i] );
760 if ( likely( p_seekpoint_copy ) )
761 TAB_APPEND( p_title->i_seekpoint, p_title->seekpoint, p_seekpoint_copy );
763 *pi_title_offset = 0;
764 *pi_seekpoint_offset = 0;
768 case DEMUX_SET_TITLE:
770 const int i_title = (int)va_arg( args, int );
775 case DEMUX_SET_SEEKPOINT:
777 const int i_seekpoint = (int)va_arg( args, int );
778 if( i_seekpoint > p_sys->i_seekpoints )
781 for ( int i=0; i< p_sys->i_streams; i++ )
783 if ( p_sys->pp_stream[i]->b_initializing )
787 i64 = p_sys->pp_seekpoints[i_seekpoint]->i_time_offset;
789 p_stream = Ogg_GetSelectedStream( p_demux );
792 msg_Err( p_demux, "No selected seekable stream found" );
796 stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
797 if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, i64, b ) )
799 Ogg_ResetStreamHelper( p_sys );
800 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
802 p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT;
803 p_demux->info.i_seekpoint = i_seekpoint;
811 return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
816 /****************************************************************************
817 * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
818 ****************************************************************************
819 * Returns VLC_SUCCESS if a page has been read. An error might happen if we
820 * are at the end of stream.
821 ****************************************************************************/
822 static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
824 demux_sys_t *p_ogg = p_demux->p_sys ;
828 while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
830 p_buffer = ogg_sync_buffer( &p_ogg->oy, OGGSEEK_BYTES_TO_READ );
832 i_read = stream_Read( p_demux->s, p_buffer, OGGSEEK_BYTES_TO_READ );
836 ogg_sync_wrote( &p_ogg->oy, i_read );
842 /****************************************************************************
843 * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
845 ****************************************************************************/
846 static void Ogg_UpdatePCR( demux_t *p_demux, logical_stream_t *p_stream,
847 ogg_packet *p_oggpacket )
849 demux_sys_t *p_ogg = p_demux->p_sys;
850 p_stream->i_end_trim = 0;
852 /* Convert the granulepos into a pcr */
853 if( p_oggpacket->granulepos >= 0 )
855 if( p_stream->fmt.i_codec == VLC_CODEC_THEORA ||
856 p_stream->fmt.i_codec == VLC_CODEC_KATE ||
857 p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
859 p_stream->i_pcr = Oggseek_GranuleToAbsTimestamp( p_stream,
860 p_oggpacket->granulepos, true );
865 sample = p_oggpacket->granulepos;
866 if( p_oggpacket->e_o_s &&
867 p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
868 p_stream->i_previous_granulepos >= 0 )
871 duration = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
874 ogg_int64_t end_sample;
875 end_sample = p_stream->i_previous_granulepos + duration;
876 if( end_sample > sample )
877 p_stream->i_end_trim = (int)(end_sample - sample);
880 if (sample >= p_stream->i_pre_skip)
881 sample -= p_stream->i_pre_skip;
884 p_stream->i_pcr = sample * CLOCK_FREQ / p_stream->f_rate;
887 if ( !p_ogg->i_pcr_offset )
888 p_stream->i_pcr += VLC_TS_0;
890 p_stream->i_pcr += p_ogg->i_pcr_offset;
891 p_stream->i_interpolated_pcr = p_stream->i_pcr;
896 p_stream->i_pcr = -1;
898 /* no granulepos available, try to interpolate the pcr.
899 * If we can't then don't touch the old value. */
900 if( p_stream->fmt.i_cat == VIDEO_ES )
901 /* 1 frame per packet */
902 p_stream->i_interpolated_pcr += (CLOCK_FREQ / p_stream->f_rate);
903 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
904 p_stream->i_previous_granulepos >= 0 &&
906 Ogg_OpusPacketDuration( p_stream, p_oggpacket ) ) > 0 )
909 p_oggpacket->granulepos =
910 p_stream->i_previous_granulepos + duration;
911 sample = p_oggpacket->granulepos;
912 if (sample >= p_stream->i_pre_skip)
913 sample -= p_stream->i_pre_skip;
916 p_stream->i_interpolated_pcr =
917 VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
918 p_stream->i_interpolated_pcr += p_ogg->i_pcr_offset;
920 else if( p_stream->fmt.i_bitrate )
922 p_stream->i_interpolated_pcr +=
923 ( p_oggpacket->bytes * CLOCK_FREQ /
924 p_stream->fmt.i_bitrate / 8 );
925 p_stream->i_interpolated_pcr += p_ogg->i_pcr_offset;
928 p_stream->i_previous_granulepos = p_oggpacket->granulepos;
931 /****************************************************************************
932 * Ogg_DecodePacket: Decode an Ogg packet.
933 ****************************************************************************/
934 static void Ogg_DecodePacket( demux_t *p_demux,
935 logical_stream_t *p_stream,
936 ogg_packet *p_oggpacket )
940 int i_header_len = 0;
941 mtime_t i_pts = -1, i_interpolated_pts;
942 demux_sys_t *p_ogg = p_demux->p_sys;
944 if( p_oggpacket->bytes >= 7 &&
945 ! memcmp ( p_oggpacket->packet, "Annodex", 7 ) )
947 /* it's an Annodex packet -- skip it (do nothing) */
950 else if( p_oggpacket->bytes >= 7 &&
951 ! memcmp ( p_oggpacket->packet, "AnxData", 7 ) )
953 /* it's an AnxData packet -- skip it (do nothing) */
956 else if( p_oggpacket->bytes >= 8 &&
957 ! memcmp ( p_oggpacket->packet, "fisbone", 8 ) )
959 Ogg_ReadSkeletonBones( p_demux, p_oggpacket );
962 else if( p_oggpacket->bytes >= 6 &&
963 ! memcmp ( p_oggpacket->packet, "index", 6 ) )
965 Ogg_ReadSkeletonIndex( p_demux, p_oggpacket );
969 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT && p_oggpacket->bytes > 0 &&
970 p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
972 /* Check the ES is selected */
973 if ( !p_stream->p_es )
976 es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
977 p_stream->p_es, &b_selected );
979 if( p_stream->b_force_backup )
982 p_stream->i_packets_backup++;
983 switch( p_stream->fmt.i_codec )
985 case VLC_CODEC_VORBIS:
986 case VLC_CODEC_THEORA:
987 if( p_stream->i_packets_backup == 3 )
988 p_stream->b_force_backup = false;
992 case VLC_CODEC_SPEEX:
993 if( p_stream->i_packets_backup == 2 + p_stream->i_extra_headers_packets )
994 p_stream->b_force_backup = false;
999 if( p_stream->i_packets_backup == 2 )
1000 p_stream->b_force_backup = false;
1004 case VLC_CODEC_FLAC:
1005 if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 )
1007 Ogg_ReadFlacHeader( p_demux, p_stream, p_oggpacket );
1008 p_stream->b_force_backup = false;
1010 else if( p_stream->fmt.audio.i_rate )
1012 p_stream->b_force_backup = false;
1013 if( p_oggpacket->bytes >= 9 )
1015 p_oggpacket->packet += 9;
1016 p_oggpacket->bytes -= 9;
1022 case VLC_CODEC_KATE:
1023 if( p_stream->i_packets_backup == p_stream->i_kate_num_headers )
1024 p_stream->b_force_backup = false;
1029 p_stream->b_force_backup = false;
1034 /* Backup the ogg packet (likely an header packet) */
1037 void *p_org = p_stream->p_headers;
1038 p_stream->i_headers += p_oggpacket->bytes;
1039 p_stream->p_headers = realloc( p_stream->p_headers, p_stream->i_headers );
1040 if( p_stream->p_headers )
1042 memcpy( (unsigned char *)p_stream->p_headers + p_stream->i_headers - p_oggpacket->bytes,
1043 p_oggpacket->packet, p_oggpacket->bytes );
1047 #warning Memory leak
1048 p_stream->i_headers = 0;
1049 p_stream->p_headers = NULL;
1053 else if( xiph_AppendHeaders( &p_stream->i_headers, &p_stream->p_headers,
1054 p_oggpacket->bytes, p_oggpacket->packet ) )
1056 p_stream->i_headers = 0;
1057 p_stream->p_headers = NULL;
1059 if( p_stream->i_headers > 0 )
1061 if( !p_stream->b_force_backup )
1063 /* Last header received, commit changes */
1064 free( p_stream->fmt.p_extra );
1066 p_stream->fmt.i_extra = p_stream->i_headers;
1067 p_stream->fmt.p_extra = malloc( p_stream->i_headers );
1068 if( p_stream->fmt.p_extra )
1069 memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
1070 p_stream->i_headers );
1072 p_stream->fmt.i_extra = 0;
1074 if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
1076 if ( p_ogg->p_skelstream )
1078 /* We delay until eos is reached on skeleton.
1079 * There should only be headers, as no data page is
1080 * allowed before skeleton's eos.
1081 * Skeleton data is appended to fmt on skeleton eos.
1083 p_stream->b_have_updated_format = true;
1087 if ( p_stream->p_es )
1088 /* Otherwise we set config from first headers */
1089 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
1090 p_stream->p_es, &p_stream->fmt );
1093 if( p_stream->i_headers > 0 )
1094 Ogg_ExtractMeta( p_demux, & p_stream->fmt,
1095 p_stream->p_headers, p_stream->i_headers );
1097 /* we're not at BOS anymore for this logical stream */
1098 p_stream->b_initializing = false;
1102 b_selected = false; /* Discard the header packet */
1105 /* Convert the pcr into a pts */
1106 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
1107 p_stream->fmt.i_codec == VLC_CODEC_SPEEX ||
1108 p_stream->fmt.i_codec == VLC_CODEC_OPUS ||
1109 p_stream->fmt.i_codec == VLC_CODEC_FLAC )
1111 if( p_stream->i_pcr >= 0 )
1113 /* This is for streams where the granulepos of the header packets
1114 * doesn't match these of the data packets (eg. ogg web radios). */
1115 if( p_stream->i_previous_pcr == 0 &&
1116 p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
1119 /* Call the pace control */
1120 es_out_Control( p_demux->out, ES_OUT_SET_PCR,
1121 VLC_TS_0 + p_stream->i_pcr );
1124 p_stream->i_previous_pcr = p_stream->i_pcr;
1126 /* The granulepos is the end date of the sample */
1127 i_pts = p_stream->i_pcr;
1131 /* Convert the granulepos into the next pcr */
1132 i_interpolated_pts = p_stream->i_interpolated_pcr;
1133 Ogg_UpdatePCR( p_demux, p_stream, p_oggpacket );
1135 /* SPU streams are typically discontinuous, do not mind large gaps */
1136 if( p_stream->fmt.i_cat != SPU_ES )
1138 if( p_stream->i_pcr >= 0 )
1140 /* This is for streams where the granulepos of the header packets
1141 * doesn't match these of the data packets (eg. ogg web radios). */
1142 if( p_stream->i_previous_pcr == 0 &&
1143 p_stream->i_pcr > 3 * DEFAULT_PTS_DELAY )
1146 /* Call the pace control */
1147 es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_stream->i_pcr );
1152 if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
1153 p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
1154 p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
1155 p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
1156 p_stream->i_pcr >= 0 )
1158 p_stream->i_previous_pcr = p_stream->i_pcr;
1160 /* The granulepos is the start date of the sample */
1161 i_pts = p_stream->i_pcr;
1166 /* This stream isn't currently selected so we don't need to decode it,
1167 * but we did need to store its pcr as it might be selected later on */
1171 if( !( p_block = block_Alloc( p_oggpacket->bytes ) ) ) return;
1174 /* may need to preroll after a seek */
1175 if ( p_stream->i_skip_frames > 0 )
1177 if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1180 duration = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
1181 if( p_stream->i_skip_frames > duration )
1183 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1184 p_block->i_nb_samples = 0;
1185 p_stream->i_skip_frames -= duration;
1189 p_block->i_nb_samples = duration - p_stream->i_skip_frames;
1190 if( p_stream->i_previous_granulepos >=
1191 p_block->i_nb_samples + p_stream->i_pre_skip )
1193 i_pts = VLC_TS_0 + (p_stream->i_previous_granulepos
1194 - p_block->i_nb_samples - p_stream->i_pre_skip) *
1195 CLOCK_FREQ / p_stream->f_rate;
1197 p_stream->i_skip_frames = 0;
1202 p_block->i_flags |= BLOCK_FLAG_PREROLL;
1203 p_stream->i_skip_frames--;
1206 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
1207 p_block->i_nb_samples = Ogg_OpusPacketDuration( p_stream, p_oggpacket );
1211 if( i_pts == VLC_TS_INVALID ) i_pts = VLC_TS_0;
1212 else if( i_pts == -1 && i_interpolated_pts == VLC_TS_INVALID )
1214 else if( i_pts == -1 && (p_stream->fmt.i_cat == VIDEO_ES || p_stream->fmt.i_codec == VLC_CODEC_OPUS) )
1215 i_pts = i_interpolated_pts; /* FIXME : why is this incorrect for vorbis? */
1216 else if( i_pts == -1 ) i_pts = VLC_TS_INVALID;
1218 if( p_stream->fmt.i_cat == AUDIO_ES )
1220 p_block->i_dts = p_block->i_pts = i_pts;
1221 /* Blatant abuse of the i_length field. */
1222 p_block->i_length = p_stream->i_end_trim;
1224 else if( p_stream->fmt.i_cat == SPU_ES )
1226 p_block->i_dts = p_block->i_pts = i_pts;
1227 p_block->i_length = 0;
1229 else if( p_stream->fmt.i_codec == VLC_CODEC_THEORA )
1231 p_block->i_dts = p_block->i_pts = i_pts;
1232 if( (p_oggpacket->granulepos & ((1<<p_stream->i_granule_shift)-1)) == 0 )
1234 p_block->i_flags |= BLOCK_FLAG_TYPE_I;
1237 else if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
1239 ogg_int64_t dts = p_oggpacket->granulepos >> 31;
1240 ogg_int64_t delay = (p_oggpacket->granulepos >> 9) & 0x1fff;
1242 uint64_t u_pnum = dts + delay;
1244 p_block->i_dts = p_stream->i_pcr;
1245 p_block->i_pts = VLC_TS_INVALID;
1246 /* NB, OggDirac granulepos values are in units of 2*picturerate */
1248 /* granulepos for dirac is possibly broken, this value should be ignored */
1249 if( -1 != p_oggpacket->granulepos )
1250 p_block->i_pts = u_pnum * CLOCK_FREQ / p_stream->f_rate / 2;
1254 p_block->i_dts = i_pts;
1255 p_block->i_pts = VLC_TS_INVALID;
1258 if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
1259 p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
1260 p_stream->fmt.i_codec != VLC_CODEC_OPUS &&
1261 p_stream->fmt.i_codec != VLC_CODEC_FLAC &&
1262 p_stream->fmt.i_codec != VLC_CODEC_TARKIN &&
1263 p_stream->fmt.i_codec != VLC_CODEC_THEORA &&
1264 p_stream->fmt.i_codec != VLC_CODEC_CMML &&
1265 p_stream->fmt.i_codec != VLC_CODEC_DIRAC &&
1266 p_stream->fmt.i_codec != VLC_CODEC_KATE )
1268 if( p_oggpacket->bytes <= 0 )
1270 msg_Dbg( p_demux, "discarding 0 sized packet" );
1271 block_Release( p_block );
1274 /* We remove the header from the packet */
1275 i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
1276 i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
1278 if( p_stream->fmt.i_codec == VLC_CODEC_SUBT)
1280 /* But with subtitles we need to retrieve the duration first */
1281 int i, lenbytes = 0;
1283 if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
1285 for( i = 0, lenbytes = 0; i < i_header_len; i++ )
1287 lenbytes = lenbytes << 8;
1288 lenbytes += *(p_oggpacket->packet + i_header_len - i);
1291 if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
1292 ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
1293 p_oggpacket->packet[i_header_len + 1] != 0 &&
1294 p_oggpacket->packet[i_header_len + 1] != '\n' &&
1295 p_oggpacket->packet[i_header_len + 1] != '\r' ) )
1297 p_block->i_length = (mtime_t)lenbytes * 1000;
1302 if( p_block->i_buffer >= (unsigned int)i_header_len )
1303 p_block->i_buffer -= i_header_len;
1305 p_block->i_buffer = 0;
1308 if ( p_stream->b_reusing )
1310 p_stream->b_reusing = false;
1311 p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
1314 if( p_stream->fmt.i_codec == VLC_CODEC_TARKIN )
1316 /* FIXME: the biggest hack I've ever done */
1317 msg_Warn( p_demux, "tarkin pts: %"PRId64", granule: %"PRId64,
1318 p_block->i_pts, p_block->i_dts );
1322 memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
1323 p_oggpacket->bytes - i_header_len );
1325 if ( p_stream->p_es )
1327 /* Because ES creation is delayed for preparsing */
1328 if ( p_stream->p_preparse_block )
1330 es_out_Send( p_demux->out, p_stream->p_es, p_stream->p_preparse_block );
1331 p_stream->p_preparse_block = NULL;
1333 es_out_Send( p_demux->out, p_stream->p_es, p_block );
1336 block_ChainAppend( & p_stream->p_preparse_block, p_block );
1339 /* Re-implemented to avoid linking against libopus from the demuxer. */
1340 static int Ogg_OpusPacketDuration( logical_stream_t *p_stream,
1341 ogg_packet *p_oggpacket )
1343 static const int silk_fs_div[4] = { 6000, 3000, 1500, 1000 };
1349 if( p_oggpacket->bytes < 1 )
1350 return VLC_EGENERIC;
1351 toc = p_oggpacket->packet[0];
1362 if( p_oggpacket->bytes < 2 )
1363 return VLC_EGENERIC;
1364 nframes = p_oggpacket->packet[1]&0x3F;
1367 i_rate = (int)p_stream->fmt.audio.i_rate;
1369 frame_size = (i_rate << (toc >> 3 & 3)) / 400;
1370 else if( ( toc&0x60 ) == 0x60 )
1371 frame_size = i_rate/(100 >> (toc >> 3 & 1));
1373 frame_size = i_rate*60 / silk_fs_div[toc >> 3 & 3];
1374 nsamples = nframes*frame_size;
1375 if( nsamples*25 > i_rate*3 )
1376 return VLC_EGENERIC;
1380 /****************************************************************************
1381 * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
1382 * stream and fill p_ogg.
1383 *****************************************************************************
1384 * The initial page of a logical stream is marked as a 'bos' page.
1385 * Furthermore, the Ogg specification mandates that grouped bitstreams begin
1386 * together and all of the initial pages must appear before any data pages.
1388 * On success this function returns VLC_SUCCESS.
1389 ****************************************************************************/
1390 static int Ogg_FindLogicalStreams( demux_t *p_demux )
1392 demux_sys_t *p_ogg = p_demux->p_sys ;
1393 ogg_packet oggpacket;
1396 p_ogg->i_total_length = stream_Size ( p_demux->s );
1397 msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_length );
1400 while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS )
1403 if( ogg_page_bos( &p_ogg->current_page ) )
1406 /* All is wonderful in our fine fine little world.
1407 * We found the beginning of our first logical stream. */
1408 while( ogg_page_bos( &p_ogg->current_page ) )
1410 logical_stream_t *p_stream;
1412 p_stream = malloc( sizeof(logical_stream_t) );
1413 if( unlikely( !p_stream ) )
1416 TAB_APPEND( p_ogg->i_streams, p_ogg->pp_stream, p_stream );
1418 memset( p_stream, 0, sizeof(logical_stream_t) );
1420 es_format_Init( &p_stream->fmt, 0, 0 );
1421 es_format_Init( &p_stream->fmt_old, 0, 0 );
1423 /* Setup the logical stream */
1424 p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page );
1425 ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
1427 /* Extract the initial header from the first page and verify
1428 * the codec type of this Ogg bitstream */
1429 if( ogg_stream_pagein( &p_stream->os, &p_ogg->current_page ) < 0 )
1431 /* error. stream version mismatch perhaps */
1432 msg_Err( p_demux, "error reading first page of "
1433 "Ogg bitstream data" );
1434 return VLC_EGENERIC;
1437 /* FIXME: check return value */
1438 ogg_stream_packetpeek( &p_stream->os, &oggpacket );
1440 /* Check for Vorbis header */
1441 if( oggpacket.bytes >= 7 &&
1442 ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
1444 Ogg_ReadVorbisHeader( p_stream, &oggpacket );
1445 msg_Dbg( p_demux, "found vorbis header" );
1447 /* Check for Speex header */
1448 else if( oggpacket.bytes >= 5 &&
1449 ! memcmp( oggpacket.packet, "Speex", 5 ) )
1451 Ogg_ReadSpeexHeader( p_stream, &oggpacket );
1452 msg_Dbg( p_demux, "found speex header, channels: %i, "
1453 "rate: %i, bitrate: %i",
1454 p_stream->fmt.audio.i_channels,
1455 (int)p_stream->f_rate, p_stream->fmt.i_bitrate );
1457 /* Check for Opus header */
1458 else if( oggpacket.bytes >= 8 &&
1459 ! memcmp( oggpacket.packet, "OpusHead", 8 ) )
1461 Ogg_ReadOpusHeader( p_stream, &oggpacket );
1462 msg_Dbg( p_demux, "found opus header, channels: %i, "
1464 p_stream->fmt.audio.i_channels,
1465 (int)p_stream->i_pre_skip);
1466 p_stream->i_skip_frames = p_stream->i_pre_skip;
1468 /* Check for Flac header (< version 1.1.1) */
1469 else if( oggpacket.bytes >= 4 &&
1470 ! memcmp( oggpacket.packet, "fLaC", 4 ) )
1472 msg_Dbg( p_demux, "found FLAC header" );
1474 /* Grrrr!!!! Did they really have to put all the
1475 * important info in the second header packet!!!
1476 * (STREAMINFO metadata is in the following packet) */
1477 p_stream->b_force_backup = true;
1479 p_stream->fmt.i_cat = AUDIO_ES;
1480 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1482 /* Check for Flac header (>= version 1.1.1) */
1483 else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
1484 ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
1485 ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
1487 int i_packets = ((int)oggpacket.packet[7]) << 8 |
1488 oggpacket.packet[8];
1489 msg_Dbg( p_demux, "found FLAC header version %i.%i "
1490 "(%i header packets)",
1491 oggpacket.packet[5], oggpacket.packet[6],
1494 p_stream->b_force_backup = true;
1496 p_stream->fmt.i_cat = AUDIO_ES;
1497 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
1498 oggpacket.packet += 13; oggpacket.bytes -= 13;
1499 Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket );
1501 /* Check for Theora header */
1502 else if( oggpacket.bytes >= 7 &&
1503 ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
1505 Ogg_ReadTheoraHeader( p_stream, &oggpacket );
1508 "found theora header, bitrate: %i, rate: %f",
1509 p_stream->fmt.i_bitrate, p_stream->f_rate );
1511 /* Check for Dirac header */
1512 else if( ( oggpacket.bytes >= 5 &&
1513 ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) ||
1514 ( oggpacket.bytes >= 9 &&
1515 ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) )
1517 if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) )
1518 msg_Dbg( p_demux, "found dirac header" );
1521 msg_Warn( p_demux, "found dirac header isn't decodable" );
1526 /* Check for Tarkin header */
1527 else if( oggpacket.bytes >= 7 &&
1528 ! memcmp( &oggpacket.packet[1], "tarkin", 6 ) )
1532 msg_Dbg( p_demux, "found tarkin header" );
1533 p_stream->fmt.i_cat = VIDEO_ES;
1534 p_stream->fmt.i_codec = VLC_CODEC_TARKIN;
1536 /* Cheat and get additionnal info ;) */
1537 oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
1538 oggpack_adv( &opb, 88 );
1539 oggpack_adv( &opb, 104 );
1540 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
1541 p_stream->f_rate = 2; /* FIXME */
1543 "found tarkin header, bitrate: %i, rate: %f",
1544 p_stream->fmt.i_bitrate, p_stream->f_rate );
1546 /* Check for Annodex header */
1547 else if( oggpacket.bytes >= 7 &&
1548 ! memcmp( oggpacket.packet, "Annodex", 7 ) )
1550 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1551 /* kill annodex track */
1555 /* Check for Annodex header */
1556 else if( oggpacket.bytes >= 7 &&
1557 ! memcmp( oggpacket.packet, "AnxData", 7 ) )
1559 Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1561 /* Check for Kate header */
1562 else if( oggpacket.bytes >= 8 &&
1563 ! memcmp( &oggpacket.packet[1], "kate\0\0\0", 7 ) )
1565 Ogg_ReadKateHeader( p_stream, &oggpacket );
1566 msg_Dbg( p_demux, "found kate header" );
1568 /* Check for OggDS */
1569 else if( oggpacket.bytes >= 142 &&
1570 !memcmp( &oggpacket.packet[1],
1571 "Direct Show Samples embedded in Ogg", 35 ))
1573 /* Old header type */
1574 p_stream->b_oggds = true;
1575 /* Check for video header (old format) */
1576 if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
1577 oggpacket.bytes >= 184 )
1579 p_stream->fmt.i_cat = VIDEO_ES;
1580 p_stream->fmt.i_codec =
1581 VLC_FOURCC( oggpacket.packet[68],
1582 oggpacket.packet[69],
1583 oggpacket.packet[70],
1584 oggpacket.packet[71] );
1585 msg_Dbg( p_demux, "found video header of type: %.4s",
1586 (char *)&p_stream->fmt.i_codec );
1588 p_stream->fmt.video.i_frame_rate = 10000000;
1589 p_stream->fmt.video.i_frame_rate_base =
1590 GetQWLE((oggpacket.packet+164));
1591 p_stream->f_rate = 10000000.0 /
1592 GetQWLE((oggpacket.packet+164));
1593 p_stream->fmt.video.i_bits_per_pixel =
1594 GetWLE((oggpacket.packet+182));
1595 if( !p_stream->fmt.video.i_bits_per_pixel )
1597 p_stream->fmt.video.i_bits_per_pixel = 24;
1598 p_stream->fmt.video.i_width =
1599 GetDWLE((oggpacket.packet+176));
1600 p_stream->fmt.video.i_height =
1601 GetDWLE((oggpacket.packet+180));
1604 "fps: %f, width:%i; height:%i, bitcount:%i",
1606 p_stream->fmt.video.i_width,
1607 p_stream->fmt.video.i_height,
1608 p_stream->fmt.video.i_bits_per_pixel);
1611 /* Check for audio header (old format) */
1612 else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
1615 unsigned int i_format_tag;
1617 p_stream->fmt.i_cat = AUDIO_ES;
1619 i_extra_size = GetWLE((oggpacket.packet+140));
1620 if( i_extra_size > 0 && i_extra_size < oggpacket.bytes - 142 )
1622 p_stream->fmt.i_extra = i_extra_size;
1623 p_stream->fmt.p_extra = malloc( i_extra_size );
1624 if( p_stream->fmt.p_extra )
1625 memcpy( p_stream->fmt.p_extra,
1626 oggpacket.packet + 142, i_extra_size );
1628 p_stream->fmt.i_extra = 0;
1631 i_format_tag = GetWLE((oggpacket.packet+124));
1632 p_stream->fmt.audio.i_channels =
1633 GetWLE((oggpacket.packet+126));
1634 fill_channels_info(&p_stream->fmt.audio);
1635 p_stream->f_rate = p_stream->fmt.audio.i_rate =
1636 GetDWLE((oggpacket.packet+128));
1637 p_stream->fmt.i_bitrate =
1638 GetDWLE((oggpacket.packet+132)) * 8;
1639 p_stream->fmt.audio.i_blockalign =
1640 GetWLE((oggpacket.packet+136));
1641 p_stream->fmt.audio.i_bitspersample =
1642 GetWLE((oggpacket.packet+138));
1644 wf_tag_to_fourcc( i_format_tag,
1645 &p_stream->fmt.i_codec, 0 );
1647 if( p_stream->fmt.i_codec ==
1648 VLC_FOURCC('u','n','d','f') )
1650 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1651 ( i_format_tag >> 8 ) & 0xff,
1652 i_format_tag & 0xff );
1655 msg_Dbg( p_demux, "found audio header of type: %.4s",
1656 (char *)&p_stream->fmt.i_codec );
1657 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1658 "%dbits/sample %dkb/s",
1660 p_stream->fmt.audio.i_channels,
1661 p_stream->fmt.audio.i_rate,
1662 p_stream->fmt.audio.i_bitspersample,
1663 p_stream->fmt.i_bitrate / 1024 );
1668 msg_Dbg( p_demux, "stream %d has an old header "
1669 "but is of an unknown type", p_ogg->i_streams-1 );
1674 /* Check for OggDS */
1675 else if( oggpacket.bytes >= 44+1 &&
1676 (*oggpacket.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER )
1678 stream_header_t tmp;
1679 stream_header_t *st = &tmp;
1681 p_stream->b_oggds = true;
1683 memcpy( st->streamtype, &oggpacket.packet[1+0], 8 );
1684 memcpy( st->subtype, &oggpacket.packet[1+8], 4 );
1685 st->size = GetDWLE( &oggpacket.packet[1+12] );
1686 st->time_unit = GetQWLE( &oggpacket.packet[1+16] );
1687 st->samples_per_unit = GetQWLE( &oggpacket.packet[1+24] );
1688 st->default_len = GetDWLE( &oggpacket.packet[1+32] );
1689 st->buffersize = GetDWLE( &oggpacket.packet[1+36] );
1690 st->bits_per_sample = GetWLE( &oggpacket.packet[1+40] ); // (padding 2)
1692 /* Check for video header (new format) */
1693 if( !strncmp( st->streamtype, "video", 5 ) &&
1694 oggpacket.bytes >= 52+1 )
1696 st->sh.video.width = GetDWLE( &oggpacket.packet[1+44] );
1697 st->sh.video.height = GetDWLE( &oggpacket.packet[1+48] );
1699 p_stream->fmt.i_cat = VIDEO_ES;
1701 /* We need to get rid of the header packet */
1702 ogg_stream_packetout( &p_stream->os, &oggpacket );
1704 p_stream->fmt.i_codec =
1705 VLC_FOURCC( st->subtype[0], st->subtype[1],
1706 st->subtype[2], st->subtype[3] );
1707 msg_Dbg( p_demux, "found video header of type: %.4s",
1708 (char *)&p_stream->fmt.i_codec );
1710 p_stream->fmt.video.i_frame_rate = 10000000;
1711 p_stream->fmt.video.i_frame_rate_base = st->time_unit;
1712 if( st->time_unit <= 0 )
1713 st->time_unit = 400000;
1714 p_stream->f_rate = 10000000.0 / st->time_unit;
1715 p_stream->fmt.video.i_bits_per_pixel = st->bits_per_sample;
1716 p_stream->fmt.video.i_width = st->sh.video.width;
1717 p_stream->fmt.video.i_height = st->sh.video.height;
1720 "fps: %f, width:%i; height:%i, bitcount:%i",
1722 p_stream->fmt.video.i_width,
1723 p_stream->fmt.video.i_height,
1724 p_stream->fmt.video.i_bits_per_pixel );
1726 /* Check for audio header (new format) */
1727 else if( !strncmp( st->streamtype, "audio", 5 ) &&
1728 oggpacket.bytes >= 56+1 )
1734 st->sh.audio.channels = GetWLE( &oggpacket.packet[1+44] );
1735 st->sh.audio.blockalign = GetWLE( &oggpacket.packet[1+48] );
1736 st->sh.audio.avgbytespersec = GetDWLE( &oggpacket.packet[1+52] );
1738 p_stream->fmt.i_cat = AUDIO_ES;
1740 /* We need to get rid of the header packet */
1741 ogg_stream_packetout( &p_stream->os, &oggpacket );
1743 i_extra_size = st->size - 56;
1745 if( i_extra_size > 0 &&
1746 i_extra_size < oggpacket.bytes - 1 - 56 )
1748 p_stream->fmt.i_extra = i_extra_size;
1749 p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
1750 if( p_stream->fmt.p_extra )
1751 memcpy( p_stream->fmt.p_extra, oggpacket.packet + 57,
1752 p_stream->fmt.i_extra );
1754 p_stream->fmt.i_extra = 0;
1757 memcpy( p_buffer, st->subtype, 4 );
1759 i_format_tag = strtol(p_buffer,NULL,16);
1760 p_stream->fmt.audio.i_channels = st->sh.audio.channels;
1761 fill_channels_info(&p_stream->fmt.audio);
1762 if( st->time_unit <= 0 )
1763 st->time_unit = 10000000;
1764 p_stream->f_rate = p_stream->fmt.audio.i_rate = st->samples_per_unit * 10000000 / st->time_unit;
1765 p_stream->fmt.i_bitrate = st->sh.audio.avgbytespersec * 8;
1766 p_stream->fmt.audio.i_blockalign = st->sh.audio.blockalign;
1767 p_stream->fmt.audio.i_bitspersample = st->bits_per_sample;
1769 wf_tag_to_fourcc( i_format_tag,
1770 &p_stream->fmt.i_codec, 0 );
1772 if( p_stream->fmt.i_codec ==
1773 VLC_FOURCC('u','n','d','f') )
1775 p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1776 ( i_format_tag >> 8 ) & 0xff,
1777 i_format_tag & 0xff );
1780 msg_Dbg( p_demux, "found audio header of type: %.4s",
1781 (char *)&p_stream->fmt.i_codec );
1782 msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
1783 "%dbits/sample %dkb/s",
1785 p_stream->fmt.audio.i_channels,
1786 p_stream->fmt.audio.i_rate,
1787 p_stream->fmt.audio.i_bitspersample,
1788 p_stream->fmt.i_bitrate / 1024 );
1790 /* Check for text (subtitles) header */
1791 else if( !strncmp(st->streamtype, "text", 4) )
1793 /* We need to get rid of the header packet */
1794 ogg_stream_packetout( &p_stream->os, &oggpacket );
1796 msg_Dbg( p_demux, "found text subtitle header" );
1797 p_stream->fmt.i_cat = SPU_ES;
1798 p_stream->fmt.i_codec = VLC_CODEC_SUBT;
1799 p_stream->f_rate = 1000; /* granulepos is in millisec */
1803 msg_Dbg( p_demux, "stream %d has a header marker "
1804 "but is of an unknown type", p_ogg->i_streams-1 );
1809 else if( oggpacket.bytes >= 8 &&
1810 ! memcmp( oggpacket.packet, "fishead\0", 8 ) )
1814 msg_Dbg( p_demux, "stream %d is a skeleton",
1815 p_ogg->i_streams-1 );
1816 Ogg_ReadSkeletonHeader( p_demux, p_stream, &oggpacket );
1820 msg_Dbg( p_demux, "stream %d is of unknown type",
1821 p_ogg->i_streams-1 );
1826 /* we'll need to get all headers */
1827 p_ogg->pp_stream[i_stream]->b_initializing |= p_ogg->pp_stream[i_stream]->b_force_backup;
1829 if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS )
1830 return VLC_EGENERIC;
1833 /* This is the first data page, which means we are now finished
1834 * with the initial pages. We just need to store it in the relevant
1836 for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1838 if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
1839 &p_ogg->current_page ) == 0 )
1841 p_ogg->b_page_waiting = true;
1850 return VLC_EGENERIC;
1853 /****************************************************************************
1854 * Ogg_CreateES: Creates all Elementary streams once headers are parsed
1855 ****************************************************************************/
1856 static void Ogg_CreateES( demux_t *p_demux )
1858 demux_sys_t *p_ogg = p_demux->p_sys;
1859 logical_stream_t *p_old_stream = p_ogg->p_old_stream;
1862 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1864 logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
1866 if ( p_stream->p_es == NULL )
1868 /* Better be safe than sorry when possible with ogm */
1869 if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
1870 p_stream->fmt.i_codec == VLC_CODEC_A52 )
1871 p_stream->fmt.b_packetized = false;
1873 /* Try first to reuse an old ES */
1875 p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
1876 p_old_stream->fmt.i_codec == p_stream->fmt.i_codec )
1878 msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
1880 p_stream->p_es = p_old_stream->p_es;
1881 p_stream->b_finished = false;
1882 p_stream->b_reinit = false;
1883 p_stream->b_initializing = false;
1884 p_stream->b_reusing = true;
1885 es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
1887 p_old_stream->p_es = NULL;
1888 p_old_stream = NULL;
1889 es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
1890 p_stream->p_es, &p_stream->fmt );
1894 p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
1897 // TODO: something to do here ?
1898 if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
1900 /* Set the CMML stream active */
1901 es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
1906 if( p_ogg->p_old_stream )
1908 if( p_ogg->p_old_stream->p_es )
1909 msg_Dbg( p_demux, "old stream not reused" );
1910 Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
1911 p_ogg->p_old_stream = NULL;
1915 /****************************************************************************
1916 * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
1917 * Elementary streams.
1918 ****************************************************************************/
1919 static int Ogg_BeginningOfStream( demux_t *p_demux )
1921 demux_sys_t *p_ogg = p_demux->p_sys ;
1924 /* Find the logical streams embedded in the physical stream and
1925 * initialize our p_ogg structure. */
1926 if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS )
1928 msg_Warn( p_demux, "couldn't find any ogg logical stream" );
1929 return VLC_EGENERIC;
1932 p_ogg->i_bitrate = 0;
1934 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1936 logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
1938 p_stream->p_es = NULL;
1940 /* initialise kframe index */
1943 if ( p_stream->fmt.i_bitrate == 0 &&
1944 ( p_stream->fmt.i_cat == VIDEO_ES ||
1945 p_stream->fmt.i_cat == AUDIO_ES ) )
1946 p_ogg->b_partial_bitrate = true;
1948 p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
1950 p_stream->i_pcr = p_stream->i_previous_pcr =
1951 p_stream->i_interpolated_pcr = -1;
1952 p_stream->b_reinit = false;
1955 /* get total frame count for video stream; we will need this for seeking */
1956 p_ogg->i_total_frames = 0;
1961 /****************************************************************************
1962 * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
1963 ****************************************************************************/
1964 static void Ogg_EndOfStream( demux_t *p_demux )
1966 demux_sys_t *p_ogg = p_demux->p_sys ;
1969 for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
1970 Ogg_LogicalStreamDelete( p_demux, p_ogg->pp_stream[i_stream] );
1971 free( p_ogg->pp_stream );
1974 p_ogg->i_bitrate = 0;
1975 p_ogg->i_streams = 0;
1976 p_ogg->pp_stream = NULL;
1977 p_ogg->skeleton.major = 0;
1978 p_ogg->skeleton.minor = 0;
1979 p_ogg->b_preparsing_done = false;
1980 p_ogg->i_pcr_offset = p_ogg->i_pcr;
1984 vlc_meta_Delete( p_ogg->p_meta );
1985 p_ogg->p_meta = NULL;
1987 for ( int i=0; i < p_ogg->i_seekpoints; i++ )
1989 if ( p_ogg->pp_seekpoints[i] )
1990 vlc_seekpoint_Delete( p_ogg->pp_seekpoints[i] );
1992 TAB_CLEAN( p_ogg->i_seekpoints, p_ogg->pp_seekpoints );
1993 p_ogg->i_seekpoints = 0;
1997 * This function delete and release all data associated to a logical_stream_t
1999 static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream )
2001 if( p_stream->p_es )
2002 es_out_Del( p_demux->out, p_stream->p_es );
2004 ogg_stream_clear( &p_stream->os );
2005 free( p_stream->p_headers );
2007 es_format_Clean( &p_stream->fmt_old );
2008 es_format_Clean( &p_stream->fmt );
2010 if ( p_stream->idx != NULL)
2012 oggseek_index_entries_free( p_stream->idx );
2015 Ogg_FreeSkeleton( p_stream->p_skel );
2016 p_stream->p_skel = NULL;
2017 if ( p_demux->p_sys->p_skelstream == p_stream )
2018 p_demux->p_sys->p_skelstream = NULL;
2020 /* Shouldn't happen */
2021 if ( unlikely( p_stream->p_preparse_block ) )
2023 block_ChainRelease( p_stream->p_preparse_block );
2024 p_stream->p_preparse_block = NULL;
2030 * This function check if a we need to reset a decoder in case we are
2033 static bool Ogg_IsVorbisFormatCompatible( const es_format_t *p_new, const es_format_t *p_old )
2035 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
2036 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2037 unsigned i_new_count;
2038 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
2041 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
2042 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2043 unsigned i_old_count;
2044 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
2047 bool b_match = i_new_count == i_old_count;
2048 for( unsigned i = 0; i < i_new_count && b_match; i++ )
2050 /* Ignore vorbis comment */
2053 if( pi_new_size[i] != pi_old_size[i] ||
2054 memcmp( pp_new_data[i], pp_old_data[i], pi_new_size[i] ) )
2061 static bool Ogg_IsOpusFormatCompatible( const es_format_t *p_new,
2062 const es_format_t *p_old )
2064 unsigned pi_new_size[XIPH_MAX_HEADER_COUNT];
2065 void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2066 unsigned i_new_count;
2067 if( xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
2069 unsigned pi_old_size[XIPH_MAX_HEADER_COUNT];
2070 void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2071 unsigned i_old_count;
2072 if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
2074 bool b_match = false;
2075 if( i_new_count == i_old_count && i_new_count > 0 )
2077 static const unsigned char default_map[2] = { 0, 1 };
2078 unsigned char *p_old_head;
2079 unsigned char *p_new_head;
2080 const unsigned char *p_old_map;
2081 const unsigned char *p_new_map;
2082 int i_old_channel_count;
2083 int i_new_channel_count;
2084 int i_old_stream_count;
2085 int i_new_stream_count;
2086 int i_old_coupled_count;
2087 int i_new_coupled_count;
2088 p_old_head = (unsigned char *)pp_old_data[0];
2089 i_old_channel_count = i_old_stream_count = i_old_coupled_count = 0;
2090 p_old_map = default_map;
2091 if( pi_old_size[0] >= 19 && p_old_head[8] <= 15 )
2093 i_old_channel_count = p_old_head[9];
2094 switch( p_old_head[18] )
2097 i_old_stream_count = 1;
2098 i_old_coupled_count = i_old_channel_count - 1;
2101 if( pi_old_size[0] >= 21U + i_old_channel_count )
2103 i_old_stream_count = p_old_head[19];
2104 i_old_coupled_count = p_old_head[20];
2105 p_old_map = p_old_head + 21;
2110 p_new_head = (unsigned char *)pp_new_data[0];
2111 i_new_channel_count = i_new_stream_count = i_new_coupled_count = 0;
2112 p_new_map = default_map;
2113 if( pi_new_size[0] >= 19 && p_new_head[8] <= 15 )
2115 i_new_channel_count = p_new_head[9];
2116 switch( p_new_head[18] )
2119 i_new_stream_count = 1;
2120 i_new_coupled_count = i_new_channel_count - 1;
2123 if( pi_new_size[0] >= 21U + i_new_channel_count )
2125 i_new_stream_count = p_new_head[19];
2126 i_new_coupled_count = p_new_head[20];
2127 p_new_map = p_new_head+21;
2132 b_match = i_old_channel_count == i_new_channel_count &&
2133 i_old_stream_count == i_new_stream_count &&
2134 i_old_coupled_count == i_new_coupled_count &&
2135 memcmp(p_old_map, p_new_map,
2136 i_new_channel_count*sizeof(*p_new_map)) == 0;
2142 static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream )
2144 bool b_compatible = false;
2145 if( !p_stream->fmt_old.i_cat || !p_stream->fmt_old.i_codec )
2148 /* Only Vorbis and Opus are supported. */
2149 if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2150 b_compatible = Ogg_IsVorbisFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2151 else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
2152 b_compatible = Ogg_IsOpusFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2155 msg_Warn( p_demux, "cannot reuse old stream, resetting the decoder" );
2157 return !b_compatible;
2159 static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
2160 const void *p_headers, unsigned i_headers, unsigned i_skip )
2162 demux_sys_t *p_ogg = p_demux->p_sys;
2164 unsigned pi_size[XIPH_MAX_HEADER_COUNT];
2165 void *pp_data[XIPH_MAX_HEADER_COUNT];
2167 if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
2170 /* TODO how to handle multiple comments properly ? */
2171 if( i_count >= 2 && pi_size[1] > i_skip )
2173 int i_cover_score = 0;
2174 int i_cover_idx = 0;
2175 float pf_replay_gain[AUDIO_REPLAY_GAIN_MAX];
2176 float pf_replay_peak[AUDIO_REPLAY_GAIN_MAX];
2177 for(int i=0; i< AUDIO_REPLAY_GAIN_MAX; i++ )
2179 pf_replay_gain[i] = 0;
2180 pf_replay_peak[i] = 0;
2182 vorbis_ParseComment( &p_ogg->p_meta, (uint8_t*)pp_data[1] + i_skip, pi_size[1] - i_skip,
2183 &p_ogg->i_attachments, &p_ogg->attachments,
2184 &i_cover_score, &i_cover_idx,
2185 &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints,
2186 &pf_replay_gain, &pf_replay_peak );
2187 if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
2190 snprintf( psz_url, sizeof(psz_url), "attachment://%s",
2191 p_ogg->attachments[i_cover_idx]->psz_name );
2192 vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
2195 for ( int i=0; i<AUDIO_REPLAY_GAIN_MAX;i++ )
2197 if ( pf_replay_gain[i] != 0 )
2199 p_fmt->audio_replay_gain.pb_gain[i] = true;
2200 p_fmt->audio_replay_gain.pf_gain[i] = pf_replay_gain[i];
2201 msg_Dbg( p_demux, "setting replay gain %d to %f", i, pf_replay_gain[i] );
2203 if ( pf_replay_peak[i] != 0 )
2205 p_fmt->audio_replay_gain.pb_peak[i] = true;
2206 p_fmt->audio_replay_gain.pf_peak[i] = pf_replay_peak[i];
2207 msg_Dbg( p_demux, "setting replay peak %d to %f", i, pf_replay_gain[i] );
2212 if( p_ogg->i_seekpoints > 1 )
2214 p_demux->info.i_update |= INPUT_UPDATE_TITLE_LIST;
2217 static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, int i_headers )
2219 demux_sys_t *p_ogg = p_demux->p_sys;
2221 switch( p_fmt->i_codec )
2223 /* 3 headers with the 2° one being the comments */
2224 case VLC_CODEC_VORBIS:
2225 case VLC_CODEC_THEORA:
2226 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+6 );
2228 case VLC_CODEC_OPUS:
2229 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 8 );
2231 case VLC_CODEC_SPEEX:
2232 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
2235 /* N headers with the 2° one being the comments */
2236 case VLC_CODEC_KATE:
2237 /* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
2238 Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+7+1 );
2242 case VLC_CODEC_FLAC:
2243 msg_Warn( p_demux, "Ogg_ExtractMeta does not support %4.4s", (const char*)&p_fmt->i_codec );
2247 case VLC_CODEC_CMML: /* CMML is XML text, doesn't have Vorbis comments */
2248 case VLC_CODEC_DIRAC:
2253 p_demux->info.i_update |= INPUT_UPDATE_META;
2256 static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
2257 ogg_packet *p_oggpacket )
2260 int i_fps_numerator;
2261 int i_fps_denominator;
2262 int i_keyframe_frequency_force;
2268 p_stream->fmt.i_cat = VIDEO_ES;
2269 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2271 /* Signal that we want to keep a backup of the theora
2272 * stream headers. They will be used when switching between
2274 p_stream->b_force_backup = true;
2276 /* Cheat and get additionnal info ;) */
2277 bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
2278 bs_skip( &bitstream, 56 );
2280 i_major = bs_read( &bitstream, 8 ); /* major version num */
2281 i_minor = bs_read( &bitstream, 8 ); /* minor version num */
2282 i_subminor = bs_read( &bitstream, 8 ); /* subminor version num */
2284 bs_read( &bitstream, 16 ) /*<< 4*/; /* width */
2285 bs_read( &bitstream, 16 ) /*<< 4*/; /* height */
2286 bs_read( &bitstream, 24 ); /* frame width */
2287 bs_read( &bitstream, 24 ); /* frame height */
2288 bs_read( &bitstream, 8 ); /* x offset */
2289 bs_read( &bitstream, 8 ); /* y offset */
2291 i_fps_numerator = bs_read( &bitstream, 32 );
2292 i_fps_denominator = bs_read( &bitstream, 32 );
2293 i_fps_denominator = __MAX( i_fps_denominator, 1 );
2294 bs_read( &bitstream, 24 ); /* aspect_numerator */
2295 bs_read( &bitstream, 24 ); /* aspect_denominator */
2297 p_stream->fmt.video.i_frame_rate = i_fps_numerator;
2298 p_stream->fmt.video.i_frame_rate_base = i_fps_denominator;
2300 bs_read( &bitstream, 8 ); /* colorspace */
2301 p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
2302 bs_read( &bitstream, 6 ); /* quality */
2304 i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 );
2306 /* granule_shift = i_log( frequency_force -1 ) */
2307 p_stream->i_granule_shift = 0;
2308 i_keyframe_frequency_force--;
2309 while( i_keyframe_frequency_force )
2311 p_stream->i_granule_shift++;
2312 i_keyframe_frequency_force >>= 1;
2315 i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2316 p_stream->i_keyframe_offset = 0;
2317 p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;
2319 if ( i_version >= 3002001 )
2321 p_stream->i_keyframe_offset = 1;
2325 static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
2326 ogg_packet *p_oggpacket )
2330 p_stream->fmt.i_cat = AUDIO_ES;
2331 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2333 /* Signal that we want to keep a backup of the vorbis
2334 * stream headers. They will be used when switching between
2336 p_stream->b_force_backup = true;
2338 /* Cheat and get additionnal info ;) */
2339 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2340 oggpack_adv( &opb, 88 );
2341 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2342 fill_channels_info(&p_stream->fmt.audio);
2343 p_stream->f_rate = p_stream->fmt.audio.i_rate =
2344 oggpack_read( &opb, 32 );
2345 oggpack_adv( &opb, 32 );
2346 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2349 static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
2350 ogg_packet *p_oggpacket )
2354 p_stream->fmt.i_cat = AUDIO_ES;
2355 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2357 /* Signal that we want to keep a backup of the speex
2358 * stream headers. They will be used when switching between
2360 p_stream->b_force_backup = true;
2362 /* Cheat and get additionnal info ;) */
2363 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2364 oggpack_adv( &opb, 224 );
2365 oggpack_adv( &opb, 32 ); /* speex_version_id */
2366 oggpack_adv( &opb, 32 ); /* header_size */
2367 p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
2368 oggpack_adv( &opb, 32 ); /* mode */
2369 oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
2370 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 );
2371 fill_channels_info(&p_stream->fmt.audio);
2372 p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2373 oggpack_adv( &opb, 32 ); /* frame_size */
2374 oggpack_adv( &opb, 32 ); /* vbr */
2375 oggpack_adv( &opb, 32 ); /* frames_per_packet */
2376 p_stream->i_extra_headers_packets = oggpack_read( &opb, 32 ); /* extra_headers */
2379 static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
2380 ogg_packet *p_oggpacket )
2384 p_stream->fmt.i_cat = AUDIO_ES;
2385 p_stream->fmt.i_codec = VLC_CODEC_OPUS;
2387 /* Signal that we want to keep a backup of the opus
2388 * stream headers. They will be used when switching between
2390 p_stream->b_force_backup = true;
2392 /* All OggOpus streams are timestamped at 48kHz and
2393 * can be played at 48kHz. */
2394 p_stream->f_rate = p_stream->fmt.audio.i_rate = 48000;
2395 p_stream->fmt.i_bitrate = 0;
2397 /* Cheat and get additional info ;) */
2398 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2399 oggpack_adv( &opb, 64 );
2400 oggpack_adv( &opb, 8 ); /* version_id */
2401 p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2402 fill_channels_info(&p_stream->fmt.audio);
2403 p_stream->i_pre_skip = oggpack_read( &opb, 16 );
2406 static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream,
2407 ogg_packet *p_oggpacket )
2409 /* Parse the STREAMINFO metadata */
2412 bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
2415 if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) != 0 )
2417 msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
2421 if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
2424 p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
2425 p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
2426 fill_channels_info(&p_stream->fmt.audio);
2428 msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i",
2429 p_stream->fmt.audio.i_channels, (int)p_stream->f_rate );
2433 msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
2436 /* Fake this as the last metadata block */
2437 *((uint8_t*)p_oggpacket->packet) |= 0x80;
2440 static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
2441 ogg_packet *p_oggpacket )
2449 p_stream->fmt.i_cat = SPU_ES;
2450 p_stream->fmt.i_codec = VLC_CODEC_KATE;
2452 /* Signal that we want to keep a backup of the kate
2453 * stream headers. They will be used when switching between
2455 p_stream->b_force_backup = true;
2457 /* Cheat and get additionnal info ;) */
2458 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2459 oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */
2460 p_stream->i_kate_num_headers = oggpack_read( &opb, 8 );
2461 oggpack_adv( &opb, 3*8 );
2462 p_stream->i_granule_shift = oggpack_read( &opb, 8 );
2463 oggpack_adv( &opb, 8*8 ); /* reserved */
2464 gnum = oggpack_read( &opb, 32 );
2465 gden = oggpack_read( &opb, 32 );
2466 p_stream->f_rate = (double)gnum/gden;
2468 p_stream->fmt.psz_language = malloc(16);
2469 if( p_stream->fmt.psz_language )
2471 for( n = 0; n < 16; n++ )
2472 p_stream->fmt.psz_language[n] = oggpack_read(&opb,8);
2473 p_stream->fmt.psz_language[15] = 0; /* just in case */
2477 for( n = 0; n < 16; n++ )
2478 oggpack_read(&opb,8);
2480 p_stream->fmt.psz_description = malloc(16);
2481 if( p_stream->fmt.psz_description )
2483 for( n = 0; n < 16; n++ )
2484 p_stream->fmt.psz_description[n] = oggpack_read(&opb,8);
2485 p_stream->fmt.psz_description[15] = 0; /* just in case */
2487 /* Now find a localized user readable description for this category */
2488 psz_desc = strdup(FindKateCategoryName(p_stream->fmt.psz_description));
2491 free( p_stream->fmt.psz_description );
2492 p_stream->fmt.psz_description = psz_desc;
2497 for( n = 0; n < 16; n++ )
2498 oggpack_read(&opb,8);
2502 static void Ogg_ApplyContentType( logical_stream_t *p_stream, const char* psz_value,
2503 bool *b_force_backup, bool *b_packet_out )
2505 if( !strncmp(psz_value, "audio/x-wav", 11) )
2507 /* n.b. WAVs are unsupported right now */
2508 p_stream->fmt.i_cat = UNKNOWN_ES;
2509 free( p_stream->fmt.psz_description );
2510 p_stream->fmt.psz_description = strdup("WAV Audio (Unsupported)");
2512 else if( !strncmp(psz_value, "audio/x-vorbis", 14) ||
2513 !strncmp(psz_value, "audio/vorbis", 12) )
2515 p_stream->fmt.i_cat = AUDIO_ES;
2516 p_stream->fmt.i_codec = VLC_CODEC_VORBIS;
2518 *b_force_backup = true;
2520 else if( !strncmp(psz_value, "audio/x-speex", 13) ||
2521 !strncmp(psz_value, "audio/speex", 11) )
2523 p_stream->fmt.i_cat = AUDIO_ES;
2524 p_stream->fmt.i_codec = VLC_CODEC_SPEEX;
2526 *b_force_backup = true;
2528 else if( !strncmp(psz_value, "audio/flac", 10) )
2530 p_stream->fmt.i_cat = AUDIO_ES;
2531 p_stream->fmt.i_codec = VLC_CODEC_FLAC;
2533 *b_force_backup = true;
2535 else if( !strncmp(psz_value, "video/x-theora", 14) ||
2536 !strncmp(psz_value, "video/theora", 12) )
2538 p_stream->fmt.i_cat = VIDEO_ES;
2539 p_stream->fmt.i_codec = VLC_CODEC_THEORA;
2541 *b_force_backup = true;
2543 else if( !strncmp(psz_value, "video/x-xvid", 12) )
2545 p_stream->fmt.i_cat = VIDEO_ES;
2546 p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' );
2548 *b_force_backup = true;
2550 else if( !strncmp(psz_value, "video/mpeg", 10) )
2552 /* n.b. MPEG streams are unsupported right now */
2553 p_stream->fmt.i_cat = VIDEO_ES;
2554 p_stream->fmt.i_codec = VLC_CODEC_MPGV;
2556 else if( !strncmp(psz_value, "text/x-cmml", 11) ||
2557 !strncmp(psz_value, "text/cmml", 9) )
2559 p_stream->fmt.i_cat = SPU_ES;
2560 p_stream->fmt.i_codec = VLC_CODEC_CMML;
2561 *b_packet_out = true;
2563 else if( !strncmp(psz_value, "application/kate", 16) )
2566 p_stream->fmt.i_cat = UNKNOWN_ES;
2567 free( p_stream->fmt.psz_description );
2568 p_stream->fmt.psz_description = strdup("OGG Kate Overlay (Unsupported)");
2572 static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
2573 logical_stream_t *p_stream,
2574 ogg_packet *p_oggpacket )
2576 if( p_oggpacket->bytes >= 28 &&
2577 !memcmp( p_oggpacket->packet, "Annodex", 7 ) )
2581 uint16_t major_version;
2582 uint16_t minor_version;
2583 uint64_t timebase_numerator;
2584 uint64_t timebase_denominator;
2586 Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
2588 oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2589 oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
2590 major_version = oggpack_read( &opb, 2*8 ); /* major version */
2591 minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
2592 timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
2593 timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
2595 msg_Dbg( p_demux, "Annodex info: version %"PRIu16".%"PRIu16" "
2596 "Timebase %"PRId64" / %"PRId64,
2597 major_version, minor_version,
2598 timebase_numerator, timebase_denominator );
2600 else if( p_oggpacket->bytes >= 42 &&
2601 !memcmp( p_oggpacket->packet, "AnxData", 7 ) )
2603 uint64_t granule_rate_numerator;
2604 uint64_t granule_rate_denominator;
2605 char content_type_string[1024];
2607 /* Read in Annodex header fields */
2609 granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
2610 granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
2611 p_stream->i_secondary_header_packets =
2612 GetDWLE( &p_oggpacket->packet[24] );
2614 /* we are guaranteed that the first header field will be
2615 * the content-type (by the Annodex standard) */
2616 content_type_string[0] = '\0';
2617 if( !strncasecmp( (char*)(&p_oggpacket->packet[28]), "Content-Type: ", 14 ) )
2619 uint8_t *p = memchr( &p_oggpacket->packet[42], '\r',
2620 p_oggpacket->bytes - 1 );
2621 if( p && p[0] == '\r' && p[1] == '\n' )
2622 sscanf( (char*)(&p_oggpacket->packet[42]), "%1023s\r\n",
2623 content_type_string );
2626 msg_Dbg( p_demux, "AnxData packet info: %"PRId64" / %"PRId64", %d, ``%s''",
2627 granule_rate_numerator, granule_rate_denominator,
2628 p_stream->i_secondary_header_packets, content_type_string );
2630 p_stream->f_rate = (float) granule_rate_numerator /
2631 (float) granule_rate_denominator;
2633 /* What type of file do we have?
2634 * strcmp is safe to use here because we've extracted
2635 * content_type_string from the stream manually */
2636 bool b_dopacketout = false;
2637 Ogg_ApplyContentType( p_stream, content_type_string,
2638 &p_stream->b_force_backup, &b_dopacketout );
2639 if ( b_dopacketout ) ogg_stream_packetout( &p_stream->os, p_oggpacket );
2643 static void Ogg_ReadSkeletonHeader( demux_t *p_demux, logical_stream_t *p_stream,
2644 ogg_packet *p_oggpacket )
2646 p_demux->p_sys->p_skelstream = p_stream;
2647 /* There can be only 1 skeleton for streams */
2648 p_demux->p_sys->skeleton.major = GetWLE( &p_oggpacket->packet[8] );
2649 p_demux->p_sys->skeleton.minor = GetWLE( &p_oggpacket->packet[10] );
2650 if ( asprintf( & p_stream->fmt.psz_description,
2651 "OGG Skeleton version %" PRIu16 ".%" PRIu16,
2652 p_demux->p_sys->skeleton.major,
2653 p_demux->p_sys->skeleton.minor ) < 0 )
2654 p_stream->fmt.psz_description = NULL;
2657 static void Ogg_ReadSkeletonBones( demux_t *p_demux, ogg_packet *p_oggpacket )
2659 if ( p_demux->p_sys->skeleton.major < 3 || p_oggpacket->bytes < 52 ) return;
2661 /* Find the matching stream for this skeleton data */
2662 ogg_int32_t i_serialno = GetDWLE( &p_oggpacket->packet[12] );
2663 logical_stream_t *p_target_stream = NULL;
2664 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
2666 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
2668 p_target_stream = p_demux->p_sys->pp_stream[i];
2672 if ( !p_target_stream ) return;
2674 ogg_skeleton_t *p_skel = p_target_stream->p_skel;
2677 p_skel = malloc( sizeof( ogg_skeleton_t ) );
2678 if ( !p_skel ) return;
2679 TAB_INIT( p_skel->i_messages, p_skel->ppsz_messages );
2680 p_skel->p_index = NULL;
2681 p_target_stream->p_skel = p_skel;
2684 const unsigned char *p_messages = p_oggpacket->packet + 8 + GetDWLE( &p_oggpacket->packet[8] );
2685 const unsigned char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
2686 const unsigned char *p = p_messages;
2687 while ( p <= p_boundary - 1 && p > p_oggpacket->packet )
2689 if ( *p == 0x0D && *(p+1) == 0x0A )
2691 char *psz_message = strndup( (const char *) p_messages,
2695 msg_Dbg( p_demux, "stream %" PRId32 " [%s]", i_serialno, psz_message );
2696 TAB_APPEND( p_skel->i_messages, p_skel->ppsz_messages, psz_message );
2698 if ( p < p_boundary - 1 ) p_messages = p + 2;
2705 /* Unpacks the 7bit variable encoding used in skeleton indexes */
2706 unsigned const char * Read7BitsVariableLE( unsigned const char *p_begin,
2707 unsigned const char *p_end,
2708 uint64_t *pi_value )
2714 while ( p_begin < p_end )
2716 i_read = *p_begin & 0x7F; /* High bit is start of integer */
2717 *pi_value = *pi_value | ( i_read << i_shift );
2719 if ( (*p_begin++ & 0x80) == 0x80 ) break; /* see prev */
2722 *pi_value = GetQWLE( pi_value );
2726 static void Ogg_ReadSkeletonIndex( demux_t *p_demux, ogg_packet *p_oggpacket )
2728 if ( p_demux->p_sys->skeleton.major < 4
2729 || p_oggpacket->bytes < 44 /* Need at least 1 index value (42+1+1) */
2732 /* Find the matching stream for this skeleton data */
2733 int32_t i_serialno = GetDWLE( &p_oggpacket->packet[6] );
2734 logical_stream_t *p_stream = NULL;
2735 for ( int i=0; i< p_demux->p_sys->i_streams; i++ )
2737 if ( p_demux->p_sys->pp_stream[i]->i_serial_no == i_serialno )
2739 p_stream = p_demux->p_sys->pp_stream[i];
2743 if ( !p_stream ) return;
2744 uint64_t i_keypoints = GetQWLE( &p_oggpacket->packet[10] );
2745 msg_Dbg( p_demux, "%" PRIi64 " index data for %" PRIi32, i_keypoints, i_serialno );
2746 if ( !i_keypoints ) return;
2748 p_stream->p_skel->i_indexstampden = GetQWLE( &p_oggpacket->packet[18] );
2749 p_stream->p_skel->i_indexfirstnum = GetQWLE( &p_oggpacket->packet[24] );
2750 p_stream->p_skel->i_indexlastnum = GetQWLE( &p_oggpacket->packet[32] );
2751 unsigned const char *p_fwdbyte = &p_oggpacket->packet[42];
2752 unsigned const char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
2753 uint64_t i_offset = 0;
2754 uint64_t i_time = 0;
2755 uint64_t i_keypoints_found = 0;
2757 while( p_fwdbyte < p_boundary && i_keypoints_found < i_keypoints )
2760 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
2762 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
2763 i_time += i_val * p_stream->p_skel->i_indexstampden;
2764 i_keypoints_found++;
2767 if ( i_keypoints_found != i_keypoints )
2769 msg_Warn( p_demux, "Invalid Index: missing entries" );
2773 p_stream->p_skel->p_index = malloc( p_oggpacket->bytes - 42 );
2774 if ( !p_stream->p_skel->p_index ) return;
2775 memcpy( p_stream->p_skel->p_index, &p_oggpacket->packet[42],
2776 p_oggpacket->bytes - 42 );
2777 p_stream->p_skel->i_index = i_keypoints_found;
2778 p_stream->p_skel->i_index_size = p_oggpacket->bytes - 42;
2781 static void Ogg_FreeSkeleton( ogg_skeleton_t *p_skel )
2783 if ( !p_skel ) return;
2784 for ( int i=0; i< p_skel->i_messages; i++ )
2785 free( p_skel->ppsz_messages[i] );
2786 TAB_CLEAN( p_skel->i_messages, p_skel->ppsz_messages );
2787 free( p_skel->p_index );
2791 static void Ogg_ApplySkeleton( logical_stream_t *p_stream )
2793 if ( !p_stream->p_skel ) return;
2794 for ( int i=0; i< p_stream->p_skel->i_messages; i++ )
2796 const char *psz_message = p_stream->p_skel->ppsz_messages[i];
2797 if ( ! strncmp( "Name: ", psz_message, 6 ) )
2799 free( p_stream->fmt.psz_description );
2800 p_stream->fmt.psz_description = strdup( psz_message + 6 );
2802 else if ( ! strncmp("Content-Type: ", psz_message, 14 ) )
2805 Ogg_ApplyContentType( p_stream, psz_message + 14, &b_foo, &b_foo );
2810 /* Return true if there's a skeleton exact match */
2811 bool Ogg_GetBoundsUsingSkeletonIndex( logical_stream_t *p_stream, int64_t i_time,
2812 int64_t *pi_lower, int64_t *pi_upper )
2814 if ( !p_stream || !p_stream->p_skel || !p_stream->p_skel->p_index )
2817 /* Validate range */
2818 if ( i_time < p_stream->p_skel->i_indexfirstnum
2819 * p_stream->p_skel->i_indexstampden ||
2820 i_time > p_stream->p_skel->i_indexlastnum
2821 * p_stream->p_skel->i_indexstampden ) return false;
2823 /* Then Lookup its index */
2824 unsigned const char *p_fwdbyte = p_stream->p_skel->p_index;
2829 } current = { 0, 0 }, prev = { -1, -1 };
2831 uint64_t i_keypoints_found = 0;
2833 while( p_fwdbyte < p_fwdbyte + p_stream->p_skel->i_index_size
2834 && i_keypoints_found < p_stream->p_skel->i_index )
2837 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
2838 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
2839 current.i_pos += i_val;
2840 p_fwdbyte = Read7BitsVariableLE( p_fwdbyte,
2841 p_fwdbyte + p_stream->p_skel->i_index_size, &i_val );
2842 current.i_time += i_val * p_stream->p_skel->i_indexstampden;
2843 if ( current.i_pos < 0 || current.i_time < 0 ) break;
2845 i_keypoints_found++;
2847 if ( i_time <= current.i_time )
2849 *pi_lower = prev.i_pos;
2850 *pi_upper = current.i_pos;
2851 return ( i_time == current.i_time );
2858 static uint32_t dirac_uint( bs_t *p_bs )
2860 uint32_t u_count = 0, u_value = 0;
2862 while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
2866 u_value |= bs_read( p_bs, 1 );
2869 return (1<<u_count) - 1 + u_value;
2872 static int dirac_bool( bs_t *p_bs )
2874 return bs_read( p_bs, 1 );
2877 static bool Ogg_ReadDiracHeader( logical_stream_t *p_stream,
2878 ogg_packet *p_oggpacket )
2880 static const struct {
2881 uint32_t u_n /* numerator */, u_d /* denominator */;
2882 } p_dirac_frate_tbl[] = { /* table 10.3 */
2883 {1,1}, /* this first value is never used */
2884 {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
2885 {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
2887 static const size_t u_dirac_frate_tbl = sizeof(p_dirac_frate_tbl)/sizeof(*p_dirac_frate_tbl);
2889 static const uint32_t pu_dirac_vidfmt_frate[] = { /* table C.1 */
2890 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
2892 static const size_t u_dirac_vidfmt_frate = sizeof(pu_dirac_vidfmt_frate)/sizeof(*pu_dirac_vidfmt_frate);
2896 p_stream->i_granule_shift = 22; /* not 32 */
2898 /* Backing up stream headers is not required -- seqhdrs are repeated
2899 * thoughout the stream at suitable decoding start points */
2900 p_stream->b_force_backup = false;
2902 /* read in useful bits from sequence header */
2903 bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes );
2904 bs_skip( &bs, 13*8); /* parse_info_header */
2905 dirac_uint( &bs ); /* major_version */
2906 dirac_uint( &bs ); /* minor_version */
2907 dirac_uint( &bs ); /* profile */
2908 dirac_uint( &bs ); /* level */
2910 uint32_t u_video_format = dirac_uint( &bs ); /* index */
2911 if( u_video_format >= u_dirac_vidfmt_frate )
2913 /* don't know how to parse this ogg dirac stream */
2917 if( dirac_bool( &bs ) )
2919 dirac_uint( &bs ); /* frame_width */
2920 dirac_uint( &bs ); /* frame_height */
2923 if( dirac_bool( &bs ) )
2925 dirac_uint( &bs ); /* chroma_format */
2928 if( dirac_bool( &bs ) )
2930 dirac_uint( &bs ); /* scan_format */
2933 uint32_t u_n = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_n;
2934 uint32_t u_d = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_d;
2935 if( dirac_bool( &bs ) )
2937 uint32_t u_frame_rate_index = dirac_uint( &bs );
2938 if( u_frame_rate_index >= u_dirac_frate_tbl )
2940 /* something is wrong with this stream */
2943 u_n = p_dirac_frate_tbl[u_frame_rate_index].u_n;
2944 u_d = p_dirac_frate_tbl[u_frame_rate_index].u_d;
2945 if( u_frame_rate_index == 0 )
2947 u_n = dirac_uint( &bs ); /* frame_rate_numerator */
2948 u_d = dirac_uint( &bs ); /* frame_rate_denominator */
2951 p_stream->f_rate = (float) u_n / u_d;
2953 /* probably is an ogg dirac es */
2954 p_stream->fmt.i_cat = VIDEO_ES;
2955 p_stream->fmt.i_codec = VLC_CODEC_DIRAC;