1 /*****************************************************************************
2 * vorbis.c Vorbis audio packetizer
3 *****************************************************************************
4 * Copyright (C) 2001, 2002 VideoLAN
5 * $Id: vorbis.c,v 1.1 2003/06/23 23:51:31 gbazin Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <vlc/decoder.h>
30 #include <vlc/input.h>
33 #include <stdlib.h> /* malloc(), free() */
34 #include <string.h> /* strdup() */
35 #include "codecs.h" /* WAVEFORMATEX BITMAPINFOHEADER */
38 #include <vorbis/codec.h>
40 /*****************************************************************************
42 *****************************************************************************/
43 typedef struct packetizer_s
48 decoder_fifo_t *p_fifo; /* stores the PES stream data */
49 pes_packet_t *p_pes; /* current PES we are decoding */
51 /* Output properties */
52 sout_packetizer_input_t *p_sout_input;
53 sout_format_t output_format;
58 vorbis_info vi; /* struct that stores all the static vorbis bitstream
60 vorbis_comment vc; /* struct that stores all the bitstream user
62 vorbis_dsp_state vd; /* central working state for the packet->PCM
64 vorbis_block vb; /* local working space for packet->PCM decode */
66 uint64_t i_samplescount;
68 mtime_t i_interpolated_pts;
69 int i_last_block_size;
73 static int Open ( vlc_object_t * );
74 static int Run ( decoder_fifo_t * );
76 static int InitThread ( packetizer_t * );
77 static void PacketizeThread ( packetizer_t * );
78 static void EndThread ( packetizer_t * );
80 static int GetOggPacket( packetizer_t *, ogg_packet *, mtime_t * );
81 static int SendOggPacket( packetizer_t *, ogg_packet *, mtime_t, int );
83 #define FREE( p ) if( p ) free( p ); p = NULL
85 /*****************************************************************************
87 *****************************************************************************/
89 set_description( _("Vorbis audio packetizer") );
90 set_capability( "packetizer", 50 );
91 set_callbacks( Open, NULL );
94 /*****************************************************************************
95 * OpenDecoder: probe the packetizer and return score
96 *****************************************************************************/
97 static int Open( vlc_object_t *p_this )
99 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
101 if( p_fifo->i_fourcc != VLC_FOURCC( 'v', 'o', 'r', 'b') )
106 p_fifo->pf_run = Run;
110 /*****************************************************************************
111 * RunDecoder: this function is called just after the thread is created
112 *****************************************************************************/
113 static int Run( decoder_fifo_t *p_fifo )
115 packetizer_t *p_pack;
118 msg_Info( p_fifo, "Running vorbis packetizer" );
119 if( !( p_pack = malloc( sizeof( packetizer_t ) ) ) )
121 msg_Err( p_fifo, "out of memory" );
122 DecoderError( p_fifo );
125 memset( p_pack, 0, sizeof( packetizer_t ) );
127 p_pack->p_fifo = p_fifo;
129 if( InitThread( p_pack ) != 0 )
131 DecoderError( p_fifo );
135 while( ( !p_pack->p_fifo->b_die )&&( !p_pack->p_fifo->b_error ) )
137 PacketizeThread( p_pack );
141 if( ( b_error = p_pack->p_fifo->b_error ) )
143 DecoderError( p_pack->p_fifo );
158 /*****************************************************************************
159 * InitThread: initialize data before entering main loop
160 *****************************************************************************/
161 static int InitThread( packetizer_t *p_pack )
164 ogg_packet oggpacket;
166 p_pack->output_format.i_cat = AUDIO_ES;
167 p_pack->output_format.i_fourcc = p_pack->p_fifo->i_fourcc;
168 p_pack->output_format.i_sample_rate = 0;
169 p_pack->output_format.i_channels = 0;
170 p_pack->output_format.i_block_align = 0;
171 p_pack->output_format.i_bitrate = 0;
172 p_pack->output_format.i_extra_data = 0;
173 p_pack->output_format.p_extra_data = NULL;
176 p_pack->p_sout_input = NULL;
178 p_pack->i_samplescount = 0;
179 p_pack->i_interpolated_pts = 0;
181 p_pack->p_pes = NULL;
183 /* Take care of vorbis init */
184 vorbis_info_init( &p_pack->vi );
185 vorbis_comment_init( &p_pack->vc );
187 /* Take care of the initial Vorbis headers */
188 if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
191 oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
192 if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
194 msg_Err( p_pack->p_fifo, "This bitstream does not contain Vorbis "
199 /* add a input for the stream ouput */
200 p_pack->output_format.i_sample_rate = p_pack->vi.rate;
201 p_pack->output_format.i_channels = p_pack->vi.channels;
202 p_pack->output_format.i_block_align = 1;
203 p_pack->output_format.i_bitrate = p_pack->vi.bitrate_nominal;
205 p_pack->p_sout_input =
206 sout_InputNew( p_pack->p_fifo, &p_pack->output_format );
208 if( !p_pack->p_sout_input )
210 msg_Err( p_pack->p_fifo, "cannot add a new stream" );
211 p_pack->p_fifo->b_error = 1;
214 msg_Dbg( p_pack->p_fifo, "channels:%d samplerate:%d bitrate:%d",
215 p_pack->vi.channels, p_pack->vi.rate, p_pack->vi.bitrate_nominal);
217 if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
220 /* The next two packets in order are the comment and codebook headers.
221 We need to watch out that these packets are not missing as a
222 missing or corrupted header is fatal. */
223 if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
226 if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
228 msg_Err( p_pack->p_fifo, "2nd Vorbis header is corrupted" );
232 if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
235 if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
238 if( vorbis_synthesis_headerin( &p_pack->vi, &p_pack->vc, &oggpacket ) < 0 )
240 msg_Err( p_pack->p_fifo, "3rd Vorbis header is corrupted" );
244 if( SendOggPacket( p_pack, &oggpacket, 0, 0 ) != VLC_SUCCESS )
247 /* Initialize the Vorbis packet->PCM decoder */
248 vorbis_synthesis_init( &p_pack->vd, &p_pack->vi );
249 vorbis_block_init( &p_pack->vd, &p_pack->vb );
258 /*****************************************************************************
259 * PacketizeThread: packetize an unit (here copy a complete ogg packet)
260 *****************************************************************************/
261 static void PacketizeThread( packetizer_t *p_pack )
264 int i_samples, i_block_size;
265 ogg_packet oggpacket;
267 /* Timestamp all the packets */
268 if( GetOggPacket( p_pack, &oggpacket, &i_pts ) != VLC_SUCCESS )
271 if( i_pts <= 0 && p_pack->i_interpolated_pts <= 0 )
273 msg_Dbg( p_pack->p_fifo, "need a starting pts" );
277 if( i_pts > 0 ) p_pack->i_interpolated_pts = i_pts;
279 i_block_size = vorbis_packet_blocksize( &p_pack->vi, &oggpacket );
280 if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
281 i_samples = ( p_pack->i_last_block_size + i_block_size ) >> 2;
282 p_pack->i_last_block_size = i_block_size;
284 if( SendOggPacket( p_pack, &oggpacket, p_pack->i_interpolated_pts,
285 i_samples ) != VLC_SUCCESS )
288 p_pack->i_interpolated_pts += 1000000 * (uint64_t)i_samples
294 p_pack->p_fifo->b_error = 1;
297 /*****************************************************************************
298 * EndThread : packetizer thread destruction
299 *****************************************************************************/
300 static void EndThread ( packetizer_t *p_pack)
303 input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pack->p_pes );
305 vorbis_block_clear( &p_pack->vb );
306 vorbis_dsp_clear( &p_pack->vd );
307 vorbis_comment_clear( &p_pack->vc );
308 vorbis_info_clear( &p_pack->vi ); /* must be called last */
310 if( p_pack->p_sout_input )
312 sout_InputDelete( p_pack->p_sout_input );
316 /*****************************************************************************
317 * GetOggPacket: get the following vorbis packet from the stream and send back
318 * the result in an ogg packet (for easy decoding by libvorbis).
319 *****************************************************************************
320 * Returns VLC_EGENERIC in case of eof.
321 *****************************************************************************/
322 static int GetOggPacket( packetizer_t *p_pack, ogg_packet *p_oggpacket,
325 if( p_pack->p_pes ) input_DeletePES( p_pack->p_fifo->p_packets_mgt,
328 input_ExtractPES( p_pack->p_fifo, &p_pack->p_pes );
329 if( !p_pack->p_pes ) return VLC_EGENERIC;
331 p_oggpacket->packet = p_pack->p_pes->p_first->p_payload_start;
332 p_oggpacket->bytes = p_pack->p_pes->i_pes_size;
333 p_oggpacket->granulepos = p_pack->p_pes->i_dts;
334 p_oggpacket->b_o_s = 0;
335 p_oggpacket->e_o_s = 0;
336 p_oggpacket->packetno = 0;
338 *p_pts = p_pack->p_pes->i_pts;
343 /*****************************************************************************
344 * SendOggPacket: send an ogg packet to the stream output.
345 *****************************************************************************
346 * Returns VLC_EGENERIC in case of error.
347 *****************************************************************************/
348 static int SendOggPacket( packetizer_t *p_pack, ogg_packet *p_oggpacket,
349 mtime_t i_pts, int i_samples )
351 sout_buffer_t *p_sout_buffer =
352 sout_BufferNew( p_pack->p_sout_input->p_sout, p_oggpacket->bytes );
356 p_pack->p_fifo->b_error = 1;
360 p_pack->p_fifo->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
362 p_oggpacket->bytes );
364 p_sout_buffer->i_bitrate = p_pack->vi.bitrate_nominal;
366 p_sout_buffer->i_dts = i_pts;
367 p_sout_buffer->i_pts = i_pts;
369 p_sout_buffer->i_length = 1000000 * (uint64_t)i_samples / p_pack->vi.rate;
371 p_pack->i_samplescount += i_samples;
373 sout_InputSendBuffer( p_pack->p_sout_input, p_sout_buffer );