📄 ogg.c
字号:
/***************************************************************************** * ogg.c : ogg stream demux module for vlc ***************************************************************************** * Copyright (C) 2001-2003 VideoLAN * $Id: ogg.c 11054 2005-05-18 10:23:37Z gbazin $ * * Authors: Gildas Bazin <gbazin@netcourrier.com> * Andre Pang <Andre.Pang@csiro.au> (Annodex support) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <vlc/vlc.h>#include <vlc/input.h>#include <ogg/ogg.h>#include "codecs.h"#include "vlc_bits.h"/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin(); set_description( _("Ogg stream demuxer" ) ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); set_capability( "demux2", 50 ); set_callbacks( Open, Close ); add_shortcut( "ogg" );vlc_module_end();/***************************************************************************** * Definitions of structures and functions used by this plugins *****************************************************************************/typedef struct logical_stream_s{ ogg_stream_state os; /* logical stream of packets */ es_format_t fmt; es_out_id_t *p_es; double f_rate; int i_serial_no; /* the header of some logical streams (eg vorbis) contain essential * data for the decoder. We back them up here in case we need to re-feed * them to the decoder. */ int b_force_backup; int i_packets_backup; uint8_t *p_headers; int i_headers; /* program clock reference (in units of 90kHz) derived from the previous * granulepos */ mtime_t i_pcr; mtime_t i_interpolated_pcr; mtime_t i_previous_pcr; /* Misc */ int b_reinit; int i_theora_keyframe_granule_shift; /* for Annodex logical bitstreams */ int secondary_header_packets;} logical_stream_t;struct demux_sys_t{ ogg_sync_state oy; /* sync and verify incoming physical bitstream */ int i_streams; /* number of logical bitstreams */ logical_stream_t **pp_stream; /* pointer to an array of logical streams */ /* program clock reference (in units of 90kHz) derived from the pcr of * the sub-streams */ mtime_t i_pcr; /* stream state */ int i_eos; /* bitrate */ int i_bitrate;};/* OggDS headers for the new header format (used in ogm files) */typedef struct stream_header_video{ ogg_int32_t width; ogg_int32_t height;} stream_header_video;typedef struct stream_header_audio{ ogg_int16_t channels; ogg_int16_t blockalign; ogg_int32_t avgbytespersec;} stream_header_audio;typedef struct stream_header{ char streamtype[8]; char subtype[4]; ogg_int32_t size; /* size of the structure */ ogg_int64_t time_unit; /* in reference time */ ogg_int64_t samples_per_unit; ogg_int32_t default_len; /* in media time */ ogg_int32_t buffersize; ogg_int16_t bits_per_sample; union { /* Video specific */ stream_header_video video; /* Audio specific */ stream_header_audio audio; } sh;} stream_header;#define OGG_BLOCK_SIZE 4096/* Some defines from OggDS */#define PACKET_TYPE_HEADER 0x01#define PACKET_TYPE_BITS 0x07#define PACKET_LEN_BITS01 0xc0#define PACKET_LEN_BITS2 0x02#define PACKET_IS_SYNCPOINT 0x08/***************************************************************************** * Local prototypes *****************************************************************************/static int Demux ( demux_t * );static int Control( demux_t *, int, va_list );/* Bitstream manipulation */static int Ogg_ReadPage ( demux_t *, ogg_page * );static void Ogg_UpdatePCR ( logical_stream_t *, ogg_packet * );static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet * );static int Ogg_BeginningOfStream( demux_t *p_demux );static int Ogg_FindLogicalStreams( demux_t *p_demux );static void Ogg_EndOfStream( demux_t *p_demux );/* Logical bitstream headers */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_ReadFlacHeader( demux_t *, logical_stream_t *, ogg_packet * );static void Ogg_ReadAnnodexHeader( vlc_object_t *, logical_stream_t *, ogg_packet * );/***************************************************************************** * Open: initializes ogg demux structures *****************************************************************************/static int Open( vlc_object_t * p_this ){ demux_t *p_demux = (demux_t *)p_this; demux_sys_t *p_sys; uint8_t *p_peek; /* Check if we are dealing with an ogg stream */ if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC; if( strcmp( p_demux->psz_demux, "ogg" ) && strncmp( p_peek, "OggS", 4 ) ) { return VLC_EGENERIC; } /* Set exported functions */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) ); p_sys->i_bitrate = 0; p_sys->pp_stream = NULL; /* Begnning of stream, tell the demux to look for elementary streams. */ p_sys->i_eos = 0; /* Initialize the Ogg physical bitstream parser */ ogg_sync_init( &p_sys->oy ); return VLC_SUCCESS;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t *)p_this; demux_sys_t *p_sys = p_demux->p_sys ; /* Cleanup the bitstream parser */ ogg_sync_clear( &p_sys->oy ); Ogg_EndOfStream( p_demux ); free( p_sys );}/***************************************************************************** * Demux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Demux( demux_t * p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; ogg_page oggpage; ogg_packet oggpacket; int i_stream; if( p_sys->i_eos == p_sys->i_streams ) { if( p_sys->i_eos ) { msg_Dbg( p_demux, "end of a group of logical streams" ); Ogg_EndOfStream( p_demux ); } p_sys->i_eos = 0; if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS ) return 0; msg_Dbg( p_demux, "beginning of a group of logical streams" ); es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); } /* * Demux an ogg page from the stream */ if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS ) { return 0; /* EOF */ } /* Test for End of Stream */ if( ogg_page_eos( &oggpage ) ) p_sys->i_eos++; for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ ) { logical_stream_t *p_stream = p_sys->pp_stream[i_stream]; if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 ) continue; while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) { /* Read info from any secondary header packets, if there are any */ if( p_stream->secondary_header_packets > 0 ) { if( p_stream->fmt.i_codec == VLC_FOURCC('t','h','e','o') && oggpacket.bytes >= 7 && ! strncmp( &oggpacket.packet[1], "theora", 6 ) ) { Ogg_ReadTheoraHeader( p_stream, &oggpacket ); p_stream->secondary_header_packets = 0; } else if( p_stream->fmt.i_codec == VLC_FOURCC('v','o','r','b') && oggpacket.bytes >= 7 && ! strncmp( &oggpacket.packet[1], "vorbis", 6 ) ) { Ogg_ReadVorbisHeader( p_stream, &oggpacket ); p_stream->secondary_header_packets = 0; } else if ( p_stream->fmt.i_codec == VLC_FOURCC('c','m','m','l') ) { p_stream->secondary_header_packets = 0; } } if( p_stream->b_reinit ) { /* If synchro is re-initialized we need to drop all the packets * until we find a new dated one. */ Ogg_UpdatePCR( p_stream, &oggpacket ); if( p_stream->i_pcr >= 0 ) { p_stream->b_reinit = 0; } else { p_stream->i_interpolated_pcr = -1; continue; } /* An Ogg/vorbis packet contains an end date granulepos */ if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) || p_stream->fmt.i_codec == VLC_FOURCC( 's','p','x',' ' ) || p_stream->fmt.i_codec == VLC_FOURCC( 'f','l','a','c' ) ) { if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) { Ogg_DecodePacket( p_demux, p_stream, &oggpacket ); } else { es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_stream->i_pcr ); } continue; } } Ogg_DecodePacket( p_demux, p_stream, &oggpacket ); } break; } i_stream = 0; p_sys->i_pcr = -1; for( ; i_stream < p_sys->i_streams; i_stream++ ) { logical_stream_t *p_stream = p_sys->pp_stream[i_stream]; if( p_stream->fmt.i_cat == SPU_ES ) continue; if( p_stream->i_interpolated_pcr < 0 ) continue; if( p_sys->i_pcr < 0 || p_stream->i_interpolated_pcr < p_sys->i_pcr ) p_sys->i_pcr = p_stream->i_interpolated_pcr; } if( p_sys->i_pcr >= 0 ) { es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -