Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

vorbis.c

00001 /*****************************************************************************
00002  * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis.
00003  *****************************************************************************
00004  * Copyright (C) 2001-2003 the VideoLAN team
00005  * $Id: vorbis.c 13044 2005-10-30 20:10:05Z gbazin $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <vlc/vlc.h>
00028 #include <vlc/decoder.h>
00029 #include <vlc/input.h>
00030 #include <vlc/sout.h>
00031 
00032 #include <ogg/ogg.h>
00033 
00034 #ifdef MODULE_NAME_IS_tremor
00035 #include <tremor/ivorbiscodec.h>
00036 
00037 #else
00038 #include <vorbis/codec.h>
00039 
00040 /* vorbis header */
00041 #ifdef HAVE_VORBIS_VORBISENC_H
00042 #   include <vorbis/vorbisenc.h>
00043 #   ifndef OV_ECTL_RATEMANAGE_AVG
00044 #       define OV_ECTL_RATEMANAGE_AVG 0x0
00045 #   endif
00046 #endif
00047 
00048 #endif
00049 
00050 /*****************************************************************************
00051  * decoder_sys_t : vorbis decoder descriptor
00052  *****************************************************************************/
00053 struct decoder_sys_t
00054 {
00055     /* Module mode */
00056     vlc_bool_t b_packetizer;
00057 
00058     /*
00059      * Input properties
00060      */
00061     int i_headers;
00062 
00063     /*
00064      * Vorbis properties
00065      */
00066     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
00067                             settings */
00068     vorbis_comment   vc; /* struct that stores all the bitstream user
00069                           * comments */
00070     vorbis_dsp_state vd; /* central working state for the packet->PCM
00071                           * decoder */
00072     vorbis_block     vb; /* local working space for packet->PCM decode */
00073 
00074     /*
00075      * Common properties
00076      */
00077     audio_date_t end_date;
00078     int          i_last_block_size;
00079 
00080     /*
00081     ** Channel reordering
00082     */
00083     int pi_chan_table[AOUT_CHAN_MAX];
00084 };
00085 
00086 static int pi_channels_maps[7] =
00087 {
00088     0,
00089     AOUT_CHAN_CENTER,
00090     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00091     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
00092     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
00093      | AOUT_CHAN_REARRIGHT,
00094     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00095      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
00096     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00097      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
00098 };
00099 
00100 /*
00101 **  channel order as defined in http://www.ogghelp.com/ogg/glossary.cfm#Audio_Channels
00102 */
00103 
00104 /* recommended vorbis channel order for 6 channels */
00105 static const uint32_t pi_6channels_in[] =
00106 { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT,  
00107   AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,AOUT_CHAN_LFE,0 };
00108 
00109 /* recommended vorbis channel order for 4 channels */
00110 static const uint32_t pi_4channels_in[] =
00111 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
00112 
00113 /* recommended vorbis channel order for 3 channels */
00114 static const uint32_t pi_3channels_in[] =
00115 { AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, 0 };
00116 
00117 /* our internal channel order (WG-4 order) */
00118 static const uint32_t pi_channels_out[] =
00119 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
00120   AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
00121 
00122 /****************************************************************************
00123  * Local prototypes
00124  ****************************************************************************/
00125 static int  OpenDecoder   ( vlc_object_t * );
00126 static int  OpenPacketizer( vlc_object_t * );
00127 static void CloseDecoder  ( vlc_object_t * );
00128 static void *DecodeBlock  ( decoder_t *, block_t ** );
00129 
00130 static int  ProcessHeaders( decoder_t * );
00131 static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
00132 
00133 static aout_buffer_t *DecodePacket  ( decoder_t *, ogg_packet * );
00134 static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
00135 
00136 static void ParseVorbisComments( decoder_t * );
00137 
00138 static void ConfigureChannelOrder(int *, int, uint32_t, vlc_bool_t );
00139 
00140 #ifdef MODULE_NAME_IS_tremor
00141 static void Interleave   ( int32_t *, const int32_t **, int, int, int * );
00142 #else
00143 static void Interleave   ( float *, const float **, int, int, int * );
00144 #endif
00145 
00146 #ifndef MODULE_NAME_IS_tremor
00147 static int OpenEncoder   ( vlc_object_t * );
00148 static void CloseEncoder ( vlc_object_t * );
00149 static block_t *Encode   ( encoder_t *, aout_buffer_t * );
00150 #endif
00151 
00152 /*****************************************************************************
00153  * Module descriptor
00154  *****************************************************************************/
00155 #define ENC_QUALITY_TEXT N_("Encoding quality")
00156 #define ENC_QUALITY_LONGTEXT N_( \
00157   "Allows you to specify a quality between 1 (low) and 10 (high), instead " \
00158   "of specifying a particular bitrate. This will produce a VBR stream." )
00159 #define ENC_MAXBR_TEXT N_("Maximum encoding bitrate")
00160 #define ENC_MAXBR_LONGTEXT N_( \
00161   "Allows you to specify a maximum bitrate in kbps. " \
00162   "Useful for streaming applications." )
00163 #define ENC_MINBR_TEXT N_("Minimum encoding bitrate")
00164 #define ENC_MINBR_LONGTEXT N_( \
00165   "Allows you to specify a minimum bitrate in kbps. " \
00166   "Useful for encoding for a fixed-size channel." )
00167 #define ENC_CBR_TEXT N_("CBR encoding")
00168 #define ENC_CBR_LONGTEXT N_( \
00169   "Allows you to force a constant bitrate encoding (CBR)." )
00170 
00171 vlc_module_begin();
00172     set_shortname( "Vorbis" );
00173     set_description( _("Vorbis audio decoder") );
00174 #ifdef MODULE_NAME_IS_tremor
00175     set_capability( "decoder", 90 );
00176 #else
00177     set_capability( "decoder", 100 );
00178 #endif
00179     set_category( CAT_INPUT );
00180     set_subcategory( SUBCAT_INPUT_ACODEC );
00181     set_callbacks( OpenDecoder, CloseDecoder );
00182 
00183     add_submodule();
00184     set_description( _("Vorbis audio packetizer") );
00185     set_capability( "packetizer", 100 );
00186     set_callbacks( OpenPacketizer, CloseDecoder );
00187 
00188 #ifndef MODULE_NAME_IS_tremor
00189 #   define ENC_CFG_PREFIX "sout-vorbis-"
00190     add_submodule();
00191     set_description( _("Vorbis audio encoder") );
00192     set_capability( "encoder", 100 );
00193 #if defined(HAVE_VORBIS_VORBISENC_H)
00194         set_callbacks( OpenEncoder, CloseEncoder );
00195 #endif
00196 
00197     add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
00198                  ENC_QUALITY_LONGTEXT, VLC_FALSE );
00199     add_integer( ENC_CFG_PREFIX "max-bitrate", 0, NULL, ENC_MAXBR_TEXT,
00200                  ENC_MAXBR_LONGTEXT, VLC_FALSE );
00201     add_integer( ENC_CFG_PREFIX "min-bitrate", 0, NULL, ENC_MINBR_TEXT,
00202                  ENC_MINBR_LONGTEXT, VLC_FALSE );
00203     add_bool( ENC_CFG_PREFIX "cbr", 0, NULL, ENC_CBR_TEXT,
00204                  ENC_CBR_LONGTEXT, VLC_FALSE );
00205 #endif
00206 
00207 vlc_module_end();
00208 
00209 #ifndef MODULE_NAME_IS_tremor
00210 static const char *ppsz_enc_options[] = {
00211     "quality", "max-bitrate", "min-bitrate", "cbr", NULL
00212 };
00213 #endif
00214 
00215 /*****************************************************************************
00216  * OpenDecoder: probe the decoder and return score
00217  *****************************************************************************/
00218 static int OpenDecoder( vlc_object_t *p_this )
00219 {
00220     decoder_t *p_dec = (decoder_t*)p_this;
00221     decoder_sys_t *p_sys;
00222 
00223     if( p_dec->fmt_in.i_codec != VLC_FOURCC('v','o','r','b') )
00224     {
00225         return VLC_EGENERIC;
00226     }
00227 
00228     /* Allocate the memory needed to store the decoder's structure */
00229     if( ( p_dec->p_sys = p_sys =
00230           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00231     {
00232         msg_Err( p_dec, "out of memory" );
00233         return VLC_EGENERIC;
00234     }
00235 
00236     /* Misc init */
00237     aout_DateSet( &p_sys->end_date, 0 );
00238     p_sys->i_last_block_size = 0;
00239     p_sys->b_packetizer = VLC_FALSE;
00240     p_sys->i_headers = 0;
00241 
00242     /* Take care of vorbis init */
00243     vorbis_info_init( &p_sys->vi );
00244     vorbis_comment_init( &p_sys->vc );
00245 
00246     /* Set output properties */
00247     p_dec->fmt_out.i_cat = AUDIO_ES;
00248 #ifdef MODULE_NAME_IS_tremor
00249     p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');
00250 #else
00251     p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
00252 #endif
00253 
00254     /* Set callbacks */
00255     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
00256         DecodeBlock;
00257     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
00258         DecodeBlock;
00259 
00260     return VLC_SUCCESS;
00261 }
00262 
00263 static int OpenPacketizer( vlc_object_t *p_this )
00264 {
00265     decoder_t *p_dec = (decoder_t*)p_this;
00266 
00267     int i_ret = OpenDecoder( p_this );
00268 
00269     if( i_ret == VLC_SUCCESS )
00270     {
00271         p_dec->p_sys->b_packetizer = VLC_TRUE;
00272         p_dec->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
00273     }
00274 
00275     return i_ret;
00276 }
00277 
00278 /****************************************************************************
00279  * DecodeBlock: the whole thing
00280  ****************************************************************************
00281  * This function must be fed with ogg packets.
00282  ****************************************************************************/
00283 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00284 {
00285     decoder_sys_t *p_sys = p_dec->p_sys;
00286     ogg_packet oggpacket;
00287 
00288     if( !pp_block ) return NULL;
00289 
00290     if( *pp_block )
00291     {
00292         /* Block to Ogg packet */
00293         oggpacket.packet = (*pp_block)->p_buffer;
00294         oggpacket.bytes = (*pp_block)->i_buffer;
00295     }
00296     else
00297     {
00298         if( p_sys->b_packetizer ) return NULL;
00299 
00300         /* Block to Ogg packet */
00301         oggpacket.packet = NULL;
00302         oggpacket.bytes = 0;
00303     }
00304 
00305     oggpacket.granulepos = -1;
00306     oggpacket.b_o_s = 0;
00307     oggpacket.e_o_s = 0;
00308     oggpacket.packetno = 0;
00309 
00310     /* Check for headers */
00311     if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
00312     {
00313         /* Headers already available as extra data */
00314         msg_Dbg( p_dec, "Headers already available as extra data" );
00315         p_sys->i_headers = 3;
00316     }
00317     else if( oggpacket.bytes && p_sys->i_headers < 3 )
00318     {
00319         /* Backup headers as extra data */
00320         uint8_t *p_extra;
00321 
00322         p_dec->fmt_in.p_extra =
00323             realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra +
00324                      oggpacket.bytes + 2 );
00325         p_extra = (uint8_t *)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra;
00326         *(p_extra++) = oggpacket.bytes >> 8;
00327         *(p_extra++) = oggpacket.bytes & 0xFF;
00328 
00329         memcpy( p_extra, oggpacket.packet, oggpacket.bytes );
00330         p_dec->fmt_in.i_extra += oggpacket.bytes + 2;
00331 
00332         block_Release( *pp_block );
00333         p_sys->i_headers++;
00334         return NULL;
00335     }
00336 
00337     if( p_sys->i_headers == 3 )
00338     {
00339         if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
00340         {
00341             p_sys->i_headers = 0;
00342             p_dec->fmt_in.i_extra = 0;
00343             block_Release( *pp_block );
00344             return NULL;
00345         }
00346         else p_sys->i_headers++;
00347     }
00348 
00349     return ProcessPacket( p_dec, &oggpacket, pp_block );
00350 }
00351 
00352 /*****************************************************************************
00353  * ProcessHeaders: process Vorbis headers.
00354  *****************************************************************************/
00355 static int ProcessHeaders( decoder_t *p_dec )
00356 {
00357     decoder_sys_t *p_sys = p_dec->p_sys;
00358     ogg_packet oggpacket;
00359     uint8_t *p_extra;
00360     int i_extra;
00361 
00362     if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
00363 
00364     oggpacket.granulepos = -1;
00365     oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
00366     oggpacket.e_o_s = 0;
00367     oggpacket.packetno = 0;
00368     p_extra = p_dec->fmt_in.p_extra;
00369     i_extra = p_dec->fmt_in.i_extra;
00370 
00371     /* Take care of the initial Vorbis header */
00372     oggpacket.bytes = *(p_extra++) << 8;
00373     oggpacket.bytes |= (*(p_extra++) & 0xFF);
00374     oggpacket.packet = p_extra;
00375     p_extra += oggpacket.bytes;
00376     i_extra -= (oggpacket.bytes + 2);
00377     if( i_extra < 0 )
00378     {
00379         msg_Err( p_dec, "header data corrupted");
00380         return VLC_EGENERIC;
00381     }
00382 
00383     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
00384     {
00385         msg_Err( p_dec, "this bitstream does not contain Vorbis audio data");
00386         return VLC_EGENERIC;
00387     }
00388 
00389     /* Setup the format */
00390     p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;
00391     p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
00392     p_dec->fmt_out.audio.i_physical_channels =
00393         p_dec->fmt_out.audio.i_original_channels =
00394             pi_channels_maps[p_sys->vi.channels];
00395     p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
00396 
00397     aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
00398     aout_DateSet( &p_sys->end_date, 0 );
00399 
00400     msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
00401              p_sys->vi.channels, p_sys->vi.rate, p_sys->vi.bitrate_nominal );
00402 
00403     /* The next packet in order is the comments header */
00404     oggpacket.b_o_s = 0;
00405     oggpacket.bytes = *(p_extra++) << 8;
00406     oggpacket.bytes |= (*(p_extra++) & 0xFF);
00407     oggpacket.packet = p_extra;
00408     p_extra += oggpacket.bytes;
00409     i_extra -= (oggpacket.bytes + 2);
00410     if( i_extra < 0 )
00411     {
00412         msg_Err( p_dec, "header data corrupted");
00413         return VLC_EGENERIC;
00414     }
00415 
00416     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
00417     {
00418         msg_Err( p_dec, "2nd Vorbis header is corrupted" );
00419         return VLC_EGENERIC;
00420     }
00421     ParseVorbisComments( p_dec );
00422 
00423     /* The next packet in order is the codebooks header
00424      * We need to watch out that this packet is not missing as a
00425      * missing or corrupted header is fatal. */
00426     oggpacket.bytes = *(p_extra++) << 8;
00427     oggpacket.bytes |= (*(p_extra++) & 0xFF);
00428     oggpacket.packet = p_extra;
00429     i_extra -= (oggpacket.bytes + 2);
00430     if( i_extra < 0 )
00431     {
00432         msg_Err( p_dec, "header data corrupted");
00433         return VLC_EGENERIC;
00434     }
00435 
00436     if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )
00437     {
00438         msg_Err( p_dec, "3rd Vorbis header is corrupted" );
00439         return VLC_EGENERIC;
00440     }
00441 
00442     if( !p_sys->b_packetizer )
00443     {
00444         /* Initialize the Vorbis packet->PCM decoder */
00445         vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
00446         vorbis_block_init( &p_sys->vd, &p_sys->vb );
00447     }
00448     else
00449     {
00450         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
00451         p_dec->fmt_out.p_extra =
00452             realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
00453         memcpy( p_dec->fmt_out.p_extra,
00454                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
00455     }
00456 
00457     ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
00458             p_dec->fmt_out.audio.i_physical_channels, VLC_TRUE);
00459 
00460     return VLC_SUCCESS;
00461 }
00462 
00463 /*****************************************************************************
00464  * ProcessPacket: processes a Vorbis packet.
00465  *****************************************************************************/
00466 static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
00467                             block_t **pp_block )
00468 {
00469     decoder_sys_t *p_sys = p_dec->p_sys;
00470     block_t *p_block = *pp_block;
00471 
00472     /* Date management */
00473     if( p_block && p_block->i_pts > 0 &&
00474         p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
00475     {
00476         aout_DateSet( &p_sys->end_date, p_block->i_pts );
00477     }
00478 
00479     if( !aout_DateGet( &p_sys->end_date ) )
00480     {
00481         /* We've just started the stream, wait for the first PTS. */
00482         if( p_block ) block_Release( p_block );
00483         return NULL;
00484     }
00485 
00486     *pp_block = NULL; /* To avoid being fed the same packet again */
00487 
00488     if( p_sys->b_packetizer )
00489     {
00490         return SendPacket( p_dec, p_oggpacket, p_block );
00491     }
00492     else
00493     {
00494         aout_buffer_t *p_aout_buffer;
00495 
00496         if( p_sys->i_headers >= 3 )
00497             p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
00498         else
00499             p_aout_buffer = NULL;
00500 
00501         if( p_block ) block_Release( p_block );
00502         return p_aout_buffer;
00503     }
00504 }
00505 
00506 /*****************************************************************************
00507  * DecodePacket: decodes a Vorbis packet.
00508  *****************************************************************************/
00509 static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
00510 {
00511     decoder_sys_t *p_sys = p_dec->p_sys;
00512     int           i_samples;
00513 
00514 #ifdef MODULE_NAME_IS_tremor
00515     int32_t       **pp_pcm;
00516 #else
00517     float         **pp_pcm;
00518 #endif
00519 
00520     if( p_oggpacket->bytes &&
00521 #ifdef MODULE_NAME_IS_tremor
00522         vorbis_synthesis( &p_sys->vb, p_oggpacket, 1 ) == 0 )
00523 #else
00524         vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
00525 #endif
00526         vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );
00527 
00528     /* **pp_pcm is a multichannel float vector. In stereo, for
00529      * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
00530      * the size of each channel. Convert the float values
00531      * (-1.<=range<=1.) to whatever PCM format and write it out */
00532 
00533     if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
00534     {
00535 
00536         aout_buffer_t *p_aout_buffer;
00537 
00538         p_aout_buffer =
00539             p_dec->pf_aout_buffer_new( p_dec, i_samples );
00540 
00541         if( p_aout_buffer == NULL ) return NULL;
00542 
00543         /* Interleave the samples */
00544 #ifdef MODULE_NAME_IS_tremor
00545         Interleave( (int32_t *)p_aout_buffer->p_buffer,
00546                     (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples, p_sys->pi_chan_table);
00547 #else
00548         Interleave( (float *)p_aout_buffer->p_buffer,
00549                     (const float **)pp_pcm, p_sys->vi.channels, i_samples, p_sys->pi_chan_table);
00550 #endif
00551 
00552         /* Tell libvorbis how many samples we actually consumed */
00553         vorbis_synthesis_read( &p_sys->vd, i_samples );
00554 
00555         /* Date management */
00556         p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
00557         p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
00558                                                       i_samples );
00559         return p_aout_buffer;
00560     }
00561     else
00562     {
00563         return NULL;
00564     }
00565 }
00566 
00567 /*****************************************************************************
00568  * SendPacket: send an ogg dated packet to the stream output.
00569  *****************************************************************************/
00570 static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
00571                             block_t *p_block )
00572 {
00573     decoder_sys_t *p_sys = p_dec->p_sys;
00574     int i_block_size, i_samples;
00575 
00576     i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
00577     if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
00578     i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
00579     p_sys->i_last_block_size = i_block_size;
00580 
00581     /* Date management */
00582     p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
00583 
00584     if( p_sys->i_headers >= 3 )
00585         p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -
00586             p_block->i_pts;
00587     else
00588         p_block->i_length = 0;
00589 
00590     return p_block;
00591 }
00592 
00593 /*****************************************************************************
00594  * ParseVorbisComments: FIXME should be done in demuxer
00595  *****************************************************************************/
00596 static void ParseVorbisComments( decoder_t *p_dec )
00597 {
00598     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
00599     char *psz_name, *psz_value, *psz_comment;
00600     int i = 0;
00601 
00602     if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
00603 
00604     while( i < p_dec->p_sys->vc.comments )
00605     {
00606         psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
00607         if( !psz_comment )
00608         {
00609             msg_Warn( p_dec, "out of memory" );
00610             break;
00611         }
00612         psz_name = psz_comment;
00613         psz_value = strchr( psz_comment, '=' );
00614         if( psz_value )
00615         {
00616             *psz_value = '\0';
00617             psz_value++;
00618             input_Control( p_input, INPUT_ADD_INFO, _("Vorbis comment"),
00619                            psz_name, psz_value );
00620             /* HACK, we should use meta */
00621             if( strcasestr( psz_name, "artist" ) )
00622             {
00623                 input_Control( p_input, INPUT_ADD_INFO, _("Meta-information"),
00624                                _("Artist"), psz_value );
00625             }
00626             else if( strcasestr( psz_name, "title" ) )
00627             {
00628                 p_input->input.p_item->psz_name = strdup( psz_value );
00629             }
00630         }
00631         /* FIXME */
00632         var_SetInteger( p_input, "item-change", p_input->input.p_item->i_id );
00633         free( psz_comment );
00634         i++;
00635     }
00636 }
00637 
00638 /*****************************************************************************
00639  * Interleave: helper function to interleave channels
00640  *****************************************************************************/
00641 static void ConfigureChannelOrder(int *pi_chan_table, int i_channels, uint32_t i_channel_mask, vlc_bool_t b_decode)
00642 {
00643     const uint32_t *pi_channels_in;
00644     switch( i_channels )
00645     {
00646         case 6:
00647         case 5:
00648             pi_channels_in = pi_6channels_in;
00649             break;
00650         case 4:
00651             pi_channels_in = pi_4channels_in;
00652             break;
00653         case 3:
00654             pi_channels_in = pi_3channels_in;
00655             break;
00656         default:
00657             {
00658                 int i;
00659                 for( i = 0; i< i_channels; ++i )
00660                 {
00661                     pi_chan_table[i] = i;
00662                 }
00663                 return;
00664             }
00665     }
00666 
00667     if( b_decode )
00668         aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
00669                                   i_channel_mask & AOUT_CHAN_PHYSMASK,
00670                                   i_channels,
00671                                   pi_chan_table );
00672     else
00673         aout_CheckChannelReorder( pi_channels_out, pi_channels_in,
00674                                   i_channel_mask & AOUT_CHAN_PHYSMASK,
00675                                   i_channels,
00676                                   pi_chan_table );
00677 }
00678 
00679 /*****************************************************************************
00680  * Interleave: helper function to interleave channels
00681  *****************************************************************************/
00682 #ifdef MODULE_NAME_IS_tremor
00683 static void Interleave( int32_t *p_out, const int32_t **pp_in,
00684                         int i_nb_channels, int i_samples, int *pi_chan_table)
00685 {
00686     int i, j;
00687 
00688     for ( j = 0; j < i_samples; j++ )
00689         for ( i = 0; i < i_nb_channels; i++ )
00690             p_out[j * i_nb_channels + pi_chan_table[i]] = pp_in[i][j] * (FIXED32_ONE >> 24);
00691 }
00692 #else
00693 static void Interleave( float *p_out, const float **pp_in,
00694                         int i_nb_channels, int i_samples, int *pi_chan_table )
00695 {
00696     int i, j;
00697 
00698     for ( j = 0; j < i_samples; j++ )
00699         for ( i = 0; i < i_nb_channels; i++ )
00700             p_out[j * i_nb_channels + pi_chan_table[i]] = pp_in[i][j];
00701 }
00702 #endif
00703 
00704 /*****************************************************************************
00705  * CloseDecoder: vorbis decoder destruction
00706  *****************************************************************************/
00707 static void CloseDecoder( vlc_object_t *p_this )
00708 {
00709     decoder_t *p_dec = (decoder_t *)p_this;
00710     decoder_sys_t *p_sys = p_dec->p_sys;
00711 
00712     if( !p_sys->b_packetizer && p_sys->i_headers > 3 )
00713     {
00714         vorbis_block_clear( &p_sys->vb );
00715         vorbis_dsp_clear( &p_sys->vd );
00716     }
00717 
00718     vorbis_comment_clear( &p_sys->vc );
00719     vorbis_info_clear( &p_sys->vi );  /* must be called last */
00720 
00721     free( p_sys );
00722 }
00723 
00724 #if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor)
00725 
00726 /*****************************************************************************
00727  * encoder_sys_t : vorbis encoder descriptor
00728  *****************************************************************************/
00729 struct encoder_sys_t
00730 {
00731     /*
00732      * Vorbis properties
00733      */
00734     vorbis_info      vi; /* struct that stores all the static vorbis bitstream
00735                             settings */
00736     vorbis_comment   vc; /* struct that stores all the bitstream user
00737                           * comments */
00738     vorbis_dsp_state vd; /* central working state for the packet->PCM
00739                           * decoder */
00740     vorbis_block     vb; /* local working space for packet->PCM decode */
00741 
00742     int i_last_block_size;
00743     int i_samples_delay;
00744     int i_channels;
00745 
00746     /*
00747      * Common properties
00748      */
00749     mtime_t i_pts;
00750 
00751     /*
00752     ** Channel reordering
00753     */
00754     int pi_chan_table[AOUT_CHAN_MAX];
00755 
00756 };
00757 
00758 /*****************************************************************************
00759  * OpenEncoder: probe the encoder and return score
00760  *****************************************************************************/
00761 static int OpenEncoder( vlc_object_t *p_this )
00762 {
00763     encoder_t *p_enc = (encoder_t *)p_this;
00764     encoder_sys_t *p_sys;
00765     int i_quality, i_min_bitrate, i_max_bitrate, i;
00766     ogg_packet header[3];
00767     vlc_value_t val;
00768     uint8_t *p_extra;
00769 
00770     if( p_enc->fmt_out.i_codec != VLC_FOURCC('v','o','r','b') &&
00771         !p_enc->b_force )
00772     {
00773         return VLC_EGENERIC;
00774     }
00775 
00776     /* Allocate the memory needed to store the decoder's structure */
00777     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
00778     {
00779         msg_Err( p_enc, "out of memory" );
00780         return VLC_EGENERIC;
00781     }
00782     p_enc->p_sys = p_sys;
00783 
00784     p_enc->pf_encode_audio = Encode;
00785     p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2');
00786     p_enc->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
00787 
00788     sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
00789 
00790     var_Get( p_enc, ENC_CFG_PREFIX "quality", &val );
00791     i_quality = val.i_int;
00792     if( i_quality > 10 ) i_quality = 10;
00793     if( i_quality < 0 ) i_quality = 0;
00794     var_Get( p_enc, ENC_CFG_PREFIX "cbr", &val );
00795     if( val.b_bool ) i_quality = 0;
00796     var_Get( p_enc, ENC_CFG_PREFIX "max-bitrate", &val );
00797     i_max_bitrate = val.i_int;
00798     var_Get( p_enc, ENC_CFG_PREFIX "min-bitrate", &val );
00799     i_min_bitrate = val.i_int;
00800 
00801     /* Initialize vorbis encoder */
00802     vorbis_info_init( &p_sys->vi );
00803 
00804     if( i_quality > 0 )
00805     {
00806         /* VBR mode */
00807         if( vorbis_encode_setup_vbr( &p_sys->vi,
00808               p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
00809               i_quality * 0.1 ) )
00810         {
00811             vorbis_info_clear( &p_sys->vi );
00812             free( p_enc->p_sys );
00813             msg_Err( p_enc, "VBR mode initialisation failed" );
00814             return VLC_EGENERIC;
00815         }
00816 
00817         /* Do we have optional hard quality restrictions? */
00818         if( i_max_bitrate > 0 || i_min_bitrate > 0 )
00819         {
00820             struct ovectl_ratemanage_arg ai;
00821             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai );
00822 
00823             ai.bitrate_hard_min = i_min_bitrate;
00824             ai.bitrate_hard_max = i_max_bitrate;
00825             ai.management_active = 1;
00826 
00827             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai );
00828 
00829         }
00830         else
00831         {
00832             /* Turn off management entirely */
00833             vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL );
00834         }
00835     }
00836     else
00837     {
00838         if( vorbis_encode_setup_managed( &p_sys->vi,
00839               p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
00840               i_min_bitrate > 0 ? i_min_bitrate * 1000: -1,
00841               p_enc->fmt_out.i_bitrate,
00842               i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) )
00843           {
00844               vorbis_info_clear( &p_sys->vi );
00845               msg_Err( p_enc, "CBR mode initialisation failed" );
00846               free( p_enc->p_sys );
00847               return VLC_EGENERIC;
00848           }
00849     }
00850 
00851     vorbis_encode_setup_init( &p_sys->vi );
00852 
00853     /* Add a comment */
00854     vorbis_comment_init( &p_sys->vc);
00855     vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");
00856 
00857     /* Set up the analysis state and auxiliary encoding storage */
00858     vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
00859     vorbis_block_init( &p_sys->vd, &p_sys->vb );
00860 
00861     /* Create and store headers */
00862     vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
00863                                &header[0], &header[1], &header[2]);
00864     p_enc->fmt_out.i_extra = 3 * 2 + header[0].bytes +
00865        header[1].bytes + header[2].bytes;
00866     p_extra = p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
00867     for( i = 0; i < 3; i++ )
00868     {
00869         *(p_extra++) = header[i].bytes >> 8;
00870         *(p_extra++) = header[i].bytes & 0xFF;
00871         memcpy( p_extra, header[i].packet, header[i].bytes );
00872         p_extra += header[i].bytes;
00873     }
00874 
00875     p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
00876     p_sys->i_last_block_size = 0;
00877     p_sys->i_samples_delay = 0;
00878     p_sys->i_pts = 0;
00879 
00880     ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
00881             p_enc->fmt_in.audio.i_physical_channels, VLC_TRUE);
00882 
00883     return VLC_SUCCESS;
00884 }
00885 
00886 /****************************************************************************
00887  * Encode: the whole thing
00888  ****************************************************************************
00889  * This function spits out ogg packets.
00890  ****************************************************************************/
00891 static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
00892 {
00893     encoder_sys_t *p_sys = p_enc->p_sys;
00894     ogg_packet oggpacket;
00895     block_t *p_block, *p_chain = NULL;
00896     float **buffer;
00897     int i;
00898     unsigned int j;
00899 
00900     p_sys->i_pts = p_aout_buf->start_date -
00901                 (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
00902                 (mtime_t)p_enc->fmt_in.audio.i_rate;
00903 
00904     p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
00905 
00906     buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );
00907 
00908     /* convert samples to float and uninterleave */
00909     for( i = 0; i < p_sys->i_channels; i++ )
00910     {
00911         for( j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
00912         {
00913             buffer[i][j]= ((float *)p_aout_buf->p_buffer)
00914                                     [j * p_sys->i_channels + p_sys->pi_chan_table[i]];
00915         }
00916     }
00917 
00918     vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );
00919 
00920     while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
00921     {
00922         int i_samples;
00923 
00924         vorbis_analysis( &p_sys->vb, NULL );
00925         vorbis_bitrate_addblock( &p_sys->vb );
00926 
00927         while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
00928         {
00929             int i_block_size;
00930             p_block = block_New( p_enc, oggpacket.bytes );
00931             memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
00932 
00933             i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );
00934 
00935             if( i_block_size < 0 ) i_block_size = 0;
00936             i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
00937             p_sys->i_last_block_size = i_block_size;
00938 
00939             p_block->i_length = (mtime_t)1000000 *
00940                 (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
00941 
00942             p_block->i_dts = p_block->i_pts = p_sys->i_pts;
00943 
00944             p_sys->i_samples_delay -= i_samples;
00945 
00946             /* Update pts */
00947             p_sys->i_pts += p_block->i_length;
00948             block_ChainAppend( &p_chain, p_block );
00949         }
00950     }
00951 
00952     return p_chain;
00953 }
00954 
00955 /*****************************************************************************
00956  * CloseEncoder: vorbis encoder destruction
00957  *****************************************************************************/
00958 static void CloseEncoder( vlc_object_t *p_this )
00959 {
00960     encoder_t *p_enc = (encoder_t *)p_this;
00961     encoder_sys_t *p_sys = p_enc->p_sys;
00962 
00963     vorbis_block_clear( &p_sys->vb );
00964     vorbis_dsp_clear( &p_sys->vd );
00965     vorbis_comment_clear( &p_sys->vc );
00966     vorbis_info_clear( &p_sys->vi );  /* must be called last */
00967 
00968     free( p_sys );
00969 }
00970 
00971 #endif /* HAVE_VORBIS_VORBISENC_H && !MODULE_NAME_IS_tremor */

Generated on Tue Dec 20 10:14:30 2005 for vlc-0.8.4a by  doxygen 1.4.2