vlc | branch: master | Gregory Maxwell <g...@xiph.org> | Tue Aug 7 15:42:05 2012 +0200| [7258c97afdf6e8209a1be5c8ce707e6040c38454] | committer: Rafaël Carré
Ogg demux: add Opus support Modified-by: Rafaël Carré <fun...@videolan.org> Signed-off-by: Rafaël Carré <fun...@videolan.org> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7258c97afdf6e8209a1be5c8ce707e6040c38454 --- modules/demux/ogg.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++- modules/demux/ogg.h | 2 ++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c index 606fbe5..e32a7c4 100644 --- a/modules/demux/ogg.c +++ b/modules/demux/ogg.c @@ -139,6 +139,7 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8 static void Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * ); +static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * ); static void Ogg_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * ); static void Ogg_ReadAnnodexHeader( vlc_object_t *, logical_stream_t *, ogg_packet * ); @@ -349,6 +350,7 @@ static int Demux( demux_t * p_demux ) /* An Ogg/vorbis packet contains an end date granulepos */ if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS || p_stream->fmt.i_codec == VLC_CODEC_SPEEX || + p_stream->fmt.i_codec == VLC_CODEC_OPUS || p_stream->fmt.i_codec == VLC_CODEC_FLAC ) { if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) @@ -602,6 +604,11 @@ static void Ogg_DecodePacket( demux_t *p_demux, b_xiph = true; break; + case VLC_CODEC_OPUS: + if( p_stream->i_packets_backup == 2 ) p_stream->b_force_backup = 0; + b_xiph = true; + break; + case VLC_CODEC_FLAC: if( !p_stream->fmt.audio.i_rate && p_stream->i_packets_backup == 2 ) { @@ -690,7 +697,19 @@ static void Ogg_DecodePacket( demux_t *p_demux, /* Convert the pcr into a pts */ if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS || p_stream->fmt.i_codec == VLC_CODEC_SPEEX || + p_stream->fmt.i_codec == VLC_CODEC_OPUS || p_stream->fmt.i_codec == VLC_CODEC_FLAC ) + if (p_stream->i_pre_skip) + { + if( i_pts > p_stream->i_pre_skip ) + { + i_pts -= - p_stream->i_pre_skip; + } + else + { + i_pts = 0; + } + } { if( p_stream->i_pcr >= 0 ) { @@ -708,7 +727,18 @@ static void Ogg_DecodePacket( demux_t *p_demux, p_stream->i_previous_pcr = p_stream->i_pcr; /* The granulepos is the end date of the sample */ - i_pts = p_stream->i_pcr; + i_pts = p_stream->i_pcr; + if (p_stream->i_pre_skip) + { + if( i_pts > p_stream->i_pre_skip ) + { + i_pts -= - p_stream->i_pre_skip; + } + else + { + i_pts = 0; + } + } } } @@ -735,6 +765,7 @@ static void Ogg_DecodePacket( demux_t *p_demux, if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS && p_stream->fmt.i_codec != VLC_CODEC_SPEEX && + p_stream->fmt.i_codec != VLC_CODEC_OPUS && p_stream->fmt.i_codec != VLC_CODEC_FLAC && p_stream->i_pcr >= 0 ) { @@ -808,6 +839,7 @@ static void Ogg_DecodePacket( demux_t *p_demux, if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS && p_stream->fmt.i_codec != VLC_CODEC_SPEEX && + p_stream->fmt.i_codec != VLC_CODEC_OPUS && p_stream->fmt.i_codec != VLC_CODEC_FLAC && p_stream->fmt.i_codec != VLC_CODEC_TARKIN && p_stream->fmt.i_codec != VLC_CODEC_THEORA && @@ -947,6 +979,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) p_stream->fmt.audio.i_channels, (int)p_stream->f_rate, p_stream->fmt.i_bitrate ); } + /* Check for Opus header */ + else if( oggpacket.bytes >= 8 && + ! memcmp( oggpacket.packet, "OpusHead", 8 ) ) + { + Ogg_ReadOpusHeader( p_stream, &oggpacket ); + msg_Dbg( p_demux, "found opus header, channels: %i, " + "pre-skip: %i", + p_stream->fmt.audio.i_channels, + (int)p_stream->i_pre_skip); + } /* Check for Flac header (< version 1.1.1) */ else if( oggpacket.bytes >= 4 && ! memcmp( oggpacket.packet, "fLaC", 4 ) ) @@ -1545,6 +1587,9 @@ static void Ogg_ExtractMeta( demux_t *p_demux, vlc_fourcc_t i_codec, const uint8 case VLC_CODEC_SPEEX: Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 0 ); break; + case VLC_CODEC_OPUS: + Ogg_ExtractXiphMeta( p_demux, p_headers, i_headers, 0 ); + break; /* N headers with the 2° one being the comments */ case VLC_CODEC_KATE: @@ -1684,6 +1729,32 @@ static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream, p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); } +static void Ogg_ReadOpusHeader( logical_stream_t *p_stream, + ogg_packet *p_oggpacket ) +{ + oggpack_buffer opb; + + p_stream->fmt.i_cat = AUDIO_ES; + p_stream->fmt.i_codec = VLC_CODEC_OPUS; + + /* Signal that we want to keep a backup of the opus + * stream headers. They will be used when switching between + * audio streams. */ + p_stream->b_force_backup = 1; + + /* All OggOpus streams are timestamped at 48kHz and + * can be played at 48kHz. */ + p_stream->f_rate = p_stream->fmt.audio.i_rate = 48000; + p_stream->fmt.i_bitrate = 0; + + /* Cheat and get additionnal info ;) */ + oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes); + oggpack_adv( &opb, 64 ); + oggpack_adv( &opb, 8 ); /* version_id */ + p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 ); + p_stream->i_pre_skip = oggpack_read( &opb, 16 ); +} + static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream, ogg_packet *p_oggpacket ) { diff --git a/modules/demux/ogg.h b/modules/demux/ogg.h index 3ad627d..6dae0a4 100644 --- a/modules/demux/ogg.h +++ b/modules/demux/ogg.h @@ -65,6 +65,8 @@ typedef struct logical_stream_s /* Misc */ bool b_reinit; int i_granule_shift; + /* Opus has a starting offset in the headers. */ + int i_pre_skip; /* offset of first keyframe for theora; can be 0 or 1 depending on version number */ int64_t i_keyframe_offset; _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org http://mailman.videolan.org/listinfo/vlc-commits