]> git.sesse.net Git - vlc/blob - modules/codec/vorbis.c
* toolbox:
[vlc] / modules / codec / vorbis.c
1 /*****************************************************************************
2  * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis.
3  *****************************************************************************
4  * Copyright (C) 2001-2003 VideoLAN
5  * $Id: vorbis.c,v 1.28 2003/12/22 02:24:51 sam Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/decoder.h>
29
30 #include <ogg/ogg.h>
31
32 #ifdef MODULE_NAME_IS_tremor
33 #include <tremor/ivorbiscodec.h>
34
35 #else
36 #include <vorbis/codec.h>
37
38 /* vorbis header */
39 #ifdef HAVE_VORBIS_VORBISENC_H
40 #   include <vorbis/vorbisenc.h>
41 #   ifndef OV_ECTL_RATEMANAGE_AVG
42 #       define OV_ECTL_RATEMANAGE_AVG 0x0
43 #   endif
44 #endif
45
46 #endif
47
48 /*****************************************************************************
49  * decoder_sys_t : vorbis decoder descriptor
50  *****************************************************************************/
51 struct decoder_sys_t
52 {
53     /* Module mode */
54     vlc_bool_t b_packetizer;
55
56     /*
57      * Input properties
58      */
59     int i_headers;
60
61     /*
62      * Vorbis properties
63      */
64     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
65                             settings */
66     vorbis_comment   vc; /* struct that stores all the bitstream user
67                           * comments */
68     vorbis_dsp_state vd; /* central working state for the packet->PCM
69                           * decoder */
70     vorbis_block     vb; /* local working space for packet->PCM decode */
71
72     /*
73      * Common properties
74      */
75     audio_date_t end_date;
76     int          i_last_block_size;
77
78 };
79
80 static int pi_channels_maps[7] =
81 {
82     0,
83     AOUT_CHAN_CENTER,
84     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
85     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
86     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
87      | AOUT_CHAN_REARRIGHT,
88     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
89      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
90     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
91      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
92 };
93
94 /****************************************************************************
95  * Local prototypes
96  ****************************************************************************/
97 static int  OpenDecoder   ( vlc_object_t * );
98 static int  OpenPacketizer( vlc_object_t * );
99 static void CloseDecoder  ( vlc_object_t * );
100 static void *DecodeBlock  ( decoder_t *, block_t ** );
101
102 static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
103
104 static aout_buffer_t *DecodePacket  ( decoder_t *, ogg_packet * );
105 static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
106
107 static void ParseVorbisComments( decoder_t * );
108
109 #ifdef MODULE_NAME_IS_tremor
110 static void Interleave   ( int32_t *, const int32_t **, int, int );
111 #else
112 static void Interleave   ( float *, const float **, int, int );
113 #endif
114
115 #ifndef MODULE_NAME_IS_tremor
116 static int OpenEncoder   ( vlc_object_t * );
117 static void CloseEncoder ( vlc_object_t * );
118 static block_t *Headers  ( encoder_t * );
119 static block_t *Encode   ( encoder_t *, aout_buffer_t * );
120 #endif
121
122 /*****************************************************************************
123  * Module descriptor
124  *****************************************************************************/
125 vlc_module_begin();
126
127     set_description( _("Vorbis audio decoder") );
128 #ifdef MODULE_NAME_IS_tremor
129     set_capability( "decoder", 90 );
130 #else
131     set_capability( "decoder", 100 );
132 #endif
133     set_callbacks( OpenDecoder, CloseDecoder );
134
135     add_submodule();
136     set_description( _("Vorbis audio packetizer") );
137     set_capability( "packetizer", 100 );
138     set_callbacks( OpenPacketizer, CloseDecoder );
139
140 #ifndef MODULE_NAME_IS_tremor
141     add_submodule();
142     set_description( _("Vorbis audio encoder") );
143     set_capability( "encoder", 100 );
144     set_callbacks( OpenEncoder, CloseEncoder );
145 #endif
146
147 vlc_module_end();
148
149 /*****************************************************************************
150  * OpenDecoder: probe the decoder and return score
151  *****************************************************************************/
152 static int OpenDecoder( vlc_object_t *p_this )
153 {
154     decoder_t *p_dec = (decoder_t*)p_this;
155     decoder_sys_t *p_sys;
156
157     if( p_dec->fmt_in.i_codec != VLC_FOURCC('v','o','r','b') )
158     {
159         return VLC_EGENERIC;
160     }
161
162     /* Allocate the memory needed to store the decoder's structure */
163     if( ( p_dec->p_sys = p_sys =
164           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
165     {
166         msg_Err( p_dec, "out of memory" );
167         return VLC_EGENERIC;
168     }
169
170     /* Misc init */
171     aout_DateSet( &p_sys->end_date, 0 );
172     p_sys->b_packetizer = VLC_FALSE;
173     p_sys->i_headers = 0;
174
175     /* Take care of vorbis init */
176     vorbis_info_init( &p_sys->vi );
177     vorbis_comment_init( &p_sys->vc );
178
179     /* Set output properties */
180     p_dec->fmt_out.i_cat = AUDIO_ES;
181 #ifdef MODULE_NAME_IS_tremor
182     p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');
183 #else
184     p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
185 #endif
186
187     /* Set callbacks */
188     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
189         DecodeBlock;
190     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
191         DecodeBlock;
192
193     return VLC_SUCCESS;
194 }
195
196 static int OpenPacketizer( vlc_object_t *p_this )
197 {
198     decoder_t *p_dec = (decoder_t*)p_this;
199
200     int i_ret = OpenDecoder( p_this );
201
202     if( i_ret == VLC_SUCCESS )
203     {
204         p_dec->p_sys->b_packetizer = VLC_TRUE;
205         p_dec->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
206     }
207
208     return i_ret;
209 }
210
211 /****************************************************************************
212  * DecodeBlock: the whole thing
213  ****************************************************************************
214  * This function must be fed with ogg packets.
215  ****************************************************************************/
216 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
217 {
218     decoder_sys_t *p_sys = p_dec->p_sys;
219     ogg_packet oggpacket;
220
221     if( !pp_block ) return NULL;
222
223     if( *pp_block )
224     {
225         /* Block to Ogg packet */
226         oggpacket.packet = (*pp_block)->p_buffer;
227         oggpacket.bytes = (*pp_block)->i_buffer;
228     }
229     else
230     {
231         if( p_sys->b_packetizer ) return NULL;
232
233         /* Block to Ogg packet */
234         oggpacket.packet = NULL;
235         oggpacket.bytes = 0;
236     }
237
238     oggpacket.granulepos = -1;
239     oggpacket.b_o_s = 0;
240     oggpacket.e_o_s = 0;
241     oggpacket.packetno = 0;
242
243     if( p_sys->i_headers == 0 )
244     {
245         /* Take care of the initial Vorbis header */
246
247         oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
248         if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc,
249                                        &oggpacket ) < 0 )
250         {
251             msg_Err( p_dec, "This bitstream does not contain Vorbis "
252                      "audio data");
253             block_Release( *pp_block );
254             return NULL;
255         }
256         p_sys->i_headers++;
257
258         /* Setup the format */
259         p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;
260         p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
261         p_dec->fmt_out.audio.i_physical_channels =
262             p_dec->fmt_out.audio.i_original_channels =
263                 pi_channels_maps[p_sys->vi.channels];
264         p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
265
266         aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
267
268         msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
269                  p_sys->vi.channels, p_sys->vi.rate,
270                  p_sys->vi.bitrate_nominal );
271
272         return ProcessPacket( p_dec, &oggpacket, pp_block );
273     }
274
275     if( p_sys->i_headers == 1 )
276     {
277         /* The next packet in order is the comments header */
278         if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
279             < 0 )
280         {
281             msg_Err( p_dec, "2nd Vorbis header is corrupted" );
282             block_Release( *pp_block );
283             return NULL;
284         }
285         p_sys->i_headers++;
286
287         ParseVorbisComments( p_dec );
288
289         return ProcessPacket( p_dec, &oggpacket, pp_block );
290     }
291
292     if( p_sys->i_headers == 2 )
293     {
294         /* The next packet in order is the codebooks header
295            We need to watch out that this packet is not missing as a
296            missing or corrupted header is fatal. */
297         if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
298             < 0 )
299         {
300             msg_Err( p_dec, "3rd Vorbis header is corrupted" );
301             block_Release( *pp_block );
302             return NULL;
303         }
304         p_sys->i_headers++;
305
306         if( !p_sys->b_packetizer )
307         {
308             /* Initialize the Vorbis packet->PCM decoder */
309             vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
310             vorbis_block_init( &p_sys->vd, &p_sys->vb );
311         }
312
313         return ProcessPacket( p_dec, &oggpacket, pp_block );
314     }
315
316     return ProcessPacket( p_dec, &oggpacket, pp_block );
317 }
318
319 /*****************************************************************************
320  * ProcessPacket: processes a Vorbis packet.
321  *****************************************************************************/
322 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
323                             block_t **pp_block )
324 {
325     decoder_sys_t *p_sys = p_dec->p_sys;
326     block_t *p_block = *pp_block;
327
328     /* Date management */
329     if( p_block && p_block->i_pts > 0 &&
330         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
331     {
332         aout_DateSet( &p_sys->end_date, p_block->i_pts );
333     }
334
335     if( !aout_DateGet( &p_sys->end_date ) )
336     {
337         /* We've just started the stream, wait for the first PTS. */
338         if( p_block ) block_Release( p_block );
339         return NULL;
340     }
341
342     *pp_block = NULL; /* To avoid being fed the same packet again */
343
344     if( p_sys->b_packetizer )
345     {
346         return SendPacket( p_dec, p_oggpacket, p_block );
347     }
348     else
349     {
350         aout_buffer_t *p_aout_buffer;
351
352         if( p_sys->i_headers >= 3 )
353             p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
354         else
355             p_aout_buffer = NULL;
356
357         if( p_block )
358         {
359             block_Release( p_block );
360         }
361         return p_aout_buffer;
362     }
363 }
364
365 /*****************************************************************************
366  * DecodePacket: decodes a Vorbis packet.
367  *****************************************************************************/
368 static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
369 {
370     decoder_sys_t *p_sys = p_dec->p_sys;
371     int           i_samples;
372
373 #ifdef MODULE_NAME_IS_tremor
374     int32_t       **pp_pcm;
375 #else
376     float         **pp_pcm;
377 #endif
378
379     if( p_oggpacket->bytes &&
380         vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
381         vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );
382
383     /* **pp_pcm is a multichannel float vector. In stereo, for
384      * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
385      * the size of each channel. Convert the float values
386      * (-1.<=range<=1.) to whatever PCM format and write it out */
387
388     if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
389     {
390
391         aout_buffer_t *p_aout_buffer;
392
393         p_aout_buffer =
394             p_dec->pf_aout_buffer_new( p_dec, i_samples );
395
396         if( p_aout_buffer == NULL ) return NULL;
397
398         /* Interleave the samples */
399 #ifdef MODULE_NAME_IS_tremor
400         Interleave( (int32_t *)p_aout_buffer->p_buffer,
401                     (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples );
402 #else
403         Interleave( (float *)p_aout_buffer->p_buffer,
404                     (const float **)pp_pcm, p_sys->vi.channels, i_samples );
405 #endif
406
407         /* Tell libvorbis how many samples we actually consumed */
408         vorbis_synthesis_read( &p_sys->vd, i_samples );
409
410         /* Date management */
411         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
412         p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
413                                                       i_samples );
414         return p_aout_buffer;
415     }
416     else
417     {
418         return NULL;
419     }
420 }
421
422 /*****************************************************************************
423  * SendPacket: send an ogg dated packet to the stream output.
424  *****************************************************************************/
425 static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
426                             block_t *p_block )
427 {
428     decoder_sys_t *p_sys = p_dec->p_sys;
429     int i_block_size, i_samples;
430
431     i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
432     if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
433     i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
434     p_sys->i_last_block_size = i_block_size;
435
436     /* Date management */
437     p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
438
439     if( p_sys->i_headers >= 3 )
440         p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -
441             p_block->i_pts;
442     else
443         p_block->i_length = 0;
444
445     return p_block;
446 }
447
448 /*****************************************************************************
449  * ParseVorbisComments: FIXME should be done in demuxer
450  *****************************************************************************/
451 static void ParseVorbisComments( decoder_t *p_dec )
452 {
453     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
454     input_info_category_t *p_cat =
455         input_InfoCategory( p_input, _("Vorbis comment") );
456     int i = 0;
457     char *psz_name, *psz_value, *psz_comment;
458     while ( i < p_dec->p_sys->vc.comments )
459     {
460         psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
461         if( !psz_comment )
462         {
463             msg_Warn( p_dec, "Out of memory" );
464             break;
465         }
466         psz_name = psz_comment;
467         psz_value = strchr( psz_comment, '=' );
468         if( psz_value )
469         {
470             *psz_value = '\0';
471             psz_value++;
472             input_AddInfo( p_cat, psz_name, psz_value );
473         }
474         free( psz_comment );
475         i++;
476     }
477 }
478
479 /*****************************************************************************
480  * Interleave: helper function to interleave channels
481  *****************************************************************************/
482 static void Interleave(
483 #ifdef MODULE_NAME_IS_tremor
484                         int32_t *p_out, const int32_t **pp_in,
485 #else
486                         float *p_out, const float **pp_in,
487 #endif
488                         int i_nb_channels, int i_samples )
489 {
490     int i, j;
491
492     for ( j = 0; j < i_samples; j++ )
493     {
494         for ( i = 0; i < i_nb_channels; i++ )
495         {
496             p_out[j * i_nb_channels + i] = pp_in[i][j];
497         }
498     }
499 }
500
501 /*****************************************************************************
502  * CloseDecoder: vorbis decoder destruction
503  *****************************************************************************/
504 static void CloseDecoder( vlc_object_t *p_this )
505 {
506     decoder_t *p_dec = (decoder_t *)p_this;
507     decoder_sys_t *p_sys = p_dec->p_sys;
508
509     if( !p_sys->b_packetizer && p_sys->i_headers >= 3 )
510     {
511         vorbis_block_clear( &p_sys->vb );
512         vorbis_dsp_clear( &p_sys->vd );
513     }
514
515     vorbis_comment_clear( &p_sys->vc );
516     vorbis_info_clear( &p_sys->vi );  /* must be called last */
517
518     free( p_sys );
519 }
520
521 #if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor)
522
523 /*****************************************************************************
524  * encoder_sys_t : theora encoder descriptor
525  *****************************************************************************/
526 struct encoder_sys_t
527 {
528     /*
529      * Input properties
530      */
531     int i_headers;
532
533     /*
534      * Vorbis properties
535      */
536     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
537                             settings */
538     vorbis_comment   vc; /* struct that stores all the bitstream user
539                           * comments */
540     vorbis_dsp_state vd; /* central working state for the packet->PCM
541                           * decoder */
542     vorbis_block     vb; /* local working space for packet->PCM decode */
543
544     int i_last_block_size;
545     int i_samples_delay;
546     int i_channels;
547
548     /*
549      * Common properties
550      */
551     mtime_t i_pts;
552 };
553
554 /*****************************************************************************
555  * OpenEncoder: probe the encoder and return score
556  *****************************************************************************/
557 static int OpenEncoder( vlc_object_t *p_this )
558 {
559     encoder_t *p_enc = (encoder_t *)p_this;
560     encoder_sys_t *p_sys;
561
562     if( p_enc->fmt_out.i_codec != VLC_FOURCC('v','o','r','b') )
563     {
564         return VLC_EGENERIC;
565     }
566
567     /* Allocate the memory needed to store the decoder's structure */
568     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
569     {
570         msg_Err( p_enc, "out of memory" );
571         return VLC_EGENERIC;
572     }
573     p_enc->p_sys = p_sys;
574
575     p_enc->pf_header = Headers;
576     p_enc->pf_encode_audio = Encode;
577     p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2');
578
579     /* Initialize vorbis encoder */
580     vorbis_info_init( &p_sys->vi );
581
582     if( vorbis_encode_setup_managed( &p_sys->vi,
583             p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
584             -1, p_enc->fmt_out.i_bitrate, -1 ) ||
585         vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_AVG, NULL ) ||
586         vorbis_encode_setup_init( &p_sys->vi ) )
587     {
588         ;
589     }
590
591     /* add a comment */
592     vorbis_comment_init( &p_sys->vc);
593     vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");
594
595     /* set up the analysis state and auxiliary encoding storage */
596     vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
597     vorbis_block_init( &p_sys->vd, &p_sys->vb );
598
599     p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
600     p_sys->i_last_block_size = 0;
601     p_sys->i_samples_delay = 0;
602     p_sys->i_headers = 0;
603     p_sys->i_pts = 0;
604
605     return VLC_SUCCESS;
606 }
607
608 /****************************************************************************
609  * Encode: the whole thing
610  ****************************************************************************
611  * This function spits out ogg packets.
612  ****************************************************************************/
613 static block_t *Headers( encoder_t *p_enc )
614 {
615     encoder_sys_t *p_sys = p_enc->p_sys;
616     block_t *p_block, *p_chain = NULL;
617
618     /* Create theora headers */
619     if( !p_sys->i_headers )
620     {
621         ogg_packet header[3];
622         int i;
623
624         vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
625                                    &header[0], &header[1], &header[2]);
626         for( i = 0; i < 3; i++ )
627         {
628             p_block = block_New( p_enc, header[i].bytes );
629             memcpy( p_block->p_buffer, header[i].packet, header[i].bytes );
630
631             p_block->i_dts = p_block->i_pts = p_block->i_length = 0;
632
633             block_ChainAppend( &p_chain, p_block );
634         }
635         p_sys->i_headers = 3;
636     }
637
638     return p_chain;
639 }
640
641 /****************************************************************************
642  * Encode: the whole thing
643  ****************************************************************************
644  * This function spits out ogg packets.
645  ****************************************************************************/
646 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
647 {
648     encoder_sys_t *p_sys = p_enc->p_sys;
649     ogg_packet oggpacket;
650     block_t *p_block, *p_chain = NULL;
651     float **buffer;
652     int i;
653     unsigned int j;
654
655     p_sys->i_pts = p_aout_buf->start_date -
656                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
657                 (mtime_t)p_enc->fmt_in.audio.i_rate;
658
659     p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
660
661     buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );
662
663     /* convert samples to float and uninterleave */
664     for( i = 0; i < p_sys->i_channels; i++ )
665     {
666         for( j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
667         {
668             buffer[i][j]= ((float)( ((int16_t *)p_aout_buf->p_buffer )
669                                     [j * p_sys->i_channels + i ] )) / 32768.f;
670         }
671     }
672
673     vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );
674
675     while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
676     {
677         int i_samples;
678
679         vorbis_analysis( &p_sys->vb, NULL );
680         vorbis_bitrate_addblock( &p_sys->vb );
681
682         while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
683         {
684             int i_block_size;
685             p_block = block_New( p_enc, oggpacket.bytes );
686             memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
687
688             i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );
689
690             if( i_block_size < 0 ) i_block_size = 0;
691             i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
692             p_sys->i_last_block_size = i_block_size;
693
694             p_block->i_length = (mtime_t)1000000 *
695                 (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
696
697             p_block->i_dts = p_block->i_pts = p_sys->i_pts;
698
699             p_sys->i_samples_delay -= i_samples;
700
701             /* Update pts */
702             p_sys->i_pts += p_block->i_length;
703             block_ChainAppend( &p_chain, p_block );
704         }
705     }
706
707     return p_chain;
708 }
709
710 /*****************************************************************************
711  * CloseEncoder: theora encoder destruction
712  *****************************************************************************/
713 static void CloseEncoder( vlc_object_t *p_this )
714 {
715     encoder_t *p_enc = (encoder_t *)p_this;
716     encoder_sys_t *p_sys = p_enc->p_sys;
717
718     vorbis_block_clear( &p_sys->vb );
719     vorbis_dsp_clear( &p_sys->vd );
720     vorbis_comment_clear( &p_sys->vc );
721     vorbis_info_clear( &p_sys->vi );  /* must be called last */
722
723     free( p_sys );
724 }
725
726 #endif /* HAVE_VORBIS_VORBISENC_H && !MODULE_NAME_IS_tremor */