vorbis.c 25.5 KB
Newer Older
Gildas Bazin's avatar
 
Gildas Bazin committed
1
/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
2
 * vorbis.c: vorbis decoder/encoder/packetizer module making use of libvorbis.
Gildas Bazin's avatar
 
Gildas Bazin committed
3
 *****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
4
 * Copyright (C) 2001-2003 VideoLAN
5
 * $Id$
Gildas Bazin's avatar
 
Gildas Bazin committed
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
Gildas Bazin's avatar
 
Gildas Bazin committed
8 9 10 11 12
 *
 * 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.
Sam Hocevar's avatar
Sam Hocevar committed
13
 *
Gildas Bazin's avatar
 
Gildas Bazin committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * 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/decoder.h>
Laurent Aimar's avatar
Laurent Aimar committed
29
#include <vlc/input.h>
30
#include <vlc/sout.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
31 32

#include <ogg/ogg.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
33

Gildas Bazin's avatar
 
Gildas Bazin committed
34 35
#ifdef MODULE_NAME_IS_tremor
#include <tremor/ivorbiscodec.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
36

Gildas Bazin's avatar
 
Gildas Bazin committed
37
#else
Gildas Bazin's avatar
 
Gildas Bazin committed
38
#include <vorbis/codec.h>
Gildas Bazin's avatar
 
Gildas Bazin committed
39 40 41 42 43 44 45 46 47

/* vorbis header */
#ifdef HAVE_VORBIS_VORBISENC_H
#   include <vorbis/vorbisenc.h>
#   ifndef OV_ECTL_RATEMANAGE_AVG
#       define OV_ECTL_RATEMANAGE_AVG 0x0
#   endif
#endif

Gildas Bazin's avatar
 
Gildas Bazin committed
48
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
49 50

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
51
 * decoder_sys_t : vorbis decoder descriptor
Gildas Bazin's avatar
 
Gildas Bazin committed
52
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
53
struct decoder_sys_t
Gildas Bazin's avatar
 
Gildas Bazin committed
54
{
Gildas Bazin's avatar
 
Gildas Bazin committed
55 56 57
    /* Module mode */
    vlc_bool_t b_packetizer;

Gildas Bazin's avatar
 
Gildas Bazin committed
58
    /*
Gildas Bazin's avatar
 
Gildas Bazin committed
59
     * Input properties
Gildas Bazin's avatar
 
Gildas Bazin committed
60
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
61
    int i_headers;
Gildas Bazin's avatar
 
Gildas Bazin committed
62 63 64 65 66 67 68 69 70 71 72 73

    /*
     * Vorbis properties
     */
    vorbis_info      vi; /* struct that stores all the static vorbis bitstream
                            settings */
    vorbis_comment   vc; /* struct that stores all the bitstream user
                          * comments */
    vorbis_dsp_state vd; /* central working state for the packet->PCM
                          * decoder */
    vorbis_block     vb; /* local working space for packet->PCM decode */

Gildas Bazin's avatar
 
Gildas Bazin committed
74 75 76
    /*
     * Common properties
     */
Gildas Bazin's avatar
 
Gildas Bazin committed
77 78
    audio_date_t end_date;
    int          i_last_block_size;
Gildas Bazin's avatar
 
Gildas Bazin committed
79 80

};
Gildas Bazin's avatar
 
Gildas Bazin committed
81

Gildas Bazin's avatar
 
Gildas Bazin committed
82
static int pi_channels_maps[7] =
83 84
{
    0,
Gildas Bazin's avatar
 
Gildas Bazin committed
85 86
    AOUT_CHAN_CENTER,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
87
    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
Gildas Bazin's avatar
 
Gildas Bazin committed
88 89
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
     | AOUT_CHAN_REARRIGHT,
90
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
Gildas Bazin's avatar
 
Gildas Bazin committed
91 92 93
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
94 95
};

Gildas Bazin's avatar
 
Gildas Bazin committed
96
/****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
97
 * Local prototypes
Gildas Bazin's avatar
 
Gildas Bazin committed
98
 ****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
99 100 101 102
static int  OpenDecoder   ( vlc_object_t * );
static int  OpenPacketizer( vlc_object_t * );
static void CloseDecoder  ( vlc_object_t * );
static void *DecodeBlock  ( decoder_t *, block_t ** );
Gildas Bazin's avatar
 
Gildas Bazin committed
103

Gildas Bazin's avatar
 
Gildas Bazin committed
104
static void *ProcessPacket ( decoder_t *, ogg_packet *, block_t ** );
Gildas Bazin's avatar
 
Gildas Bazin committed
105

Gildas Bazin's avatar
 
Gildas Bazin committed
106 107
static aout_buffer_t *DecodePacket  ( decoder_t *, ogg_packet * );
static block_t *SendPacket( decoder_t *, ogg_packet *, block_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
108 109

static void ParseVorbisComments( decoder_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
110

Gildas Bazin's avatar
 
Gildas Bazin committed
111 112 113
#ifdef MODULE_NAME_IS_tremor
static void Interleave   ( int32_t *, const int32_t **, int, int );
#else
Gildas Bazin's avatar
 
Gildas Bazin committed
114
static void Interleave   ( float *, const float **, int, int );
Gildas Bazin's avatar
 
Gildas Bazin committed
115
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
116

Gildas Bazin's avatar
 
Gildas Bazin committed
117 118 119 120 121 122 123
#ifndef MODULE_NAME_IS_tremor
static int OpenEncoder   ( vlc_object_t * );
static void CloseEncoder ( vlc_object_t * );
static block_t *Headers  ( encoder_t * );
static block_t *Encode   ( encoder_t *, aout_buffer_t * );
#endif

Gildas Bazin's avatar
 
Gildas Bazin committed
124 125 126
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
Gildas Bazin's avatar
Gildas Bazin committed
127 128 129 130 131 132 133 134 135 136 137 138 139
#define ENC_QUALITY_TEXT N_("Encoding quality")
#define ENC_QUALITY_LONGTEXT N_( \
  "Allows you to specify a quality between 1 (low) and 10 (high), instead " \
  "of specifying a particular bitrate. This will produce a VBR stream." )
#define ENC_MAXBR_TEXT N_("Maximum encoding bitrate")
#define ENC_MAXBR_LONGTEXT N_( \
  "Allows you to specify a maximum bitrate in kbps. " \
  "Useful for streaming applications." )
#define ENC_MINBR_TEXT N_("Minimum encoding bitrate")
#define ENC_MINBR_LONGTEXT N_( \
  "Allows you to specify a minimum bitrate in kbps. " \
  "Useful for encoding for a fixed-size channel." )

Gildas Bazin's avatar
 
Gildas Bazin committed
140
vlc_module_begin();
Gildas Bazin's avatar
 
Gildas Bazin committed
141

Gildas Bazin's avatar
 
Gildas Bazin committed
142
    set_description( _("Vorbis audio decoder") );
Gildas Bazin's avatar
 
Gildas Bazin committed
143 144 145
#ifdef MODULE_NAME_IS_tremor
    set_capability( "decoder", 90 );
#else
Gildas Bazin's avatar
 
Gildas Bazin committed
146
    set_capability( "decoder", 100 );
Gildas Bazin's avatar
 
Gildas Bazin committed
147
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
148
    set_callbacks( OpenDecoder, CloseDecoder );
Gildas Bazin's avatar
 
Gildas Bazin committed
149 150 151 152

    add_submodule();
    set_description( _("Vorbis audio packetizer") );
    set_capability( "packetizer", 100 );
Gildas Bazin's avatar
 
Gildas Bazin committed
153
    set_callbacks( OpenPacketizer, CloseDecoder );
Gildas Bazin's avatar
 
Gildas Bazin committed
154 155

#ifndef MODULE_NAME_IS_tremor
Gildas Bazin's avatar
Gildas Bazin committed
156
#   define ENC_CFG_PREFIX "sout-vorbis-"
Gildas Bazin's avatar
 
Gildas Bazin committed
157 158
    add_submodule();
    set_description( _("Vorbis audio encoder") );
Gildas Bazin's avatar
 
Gildas Bazin committed
159
    set_capability( "encoder", 100 );
Gildas Bazin's avatar
 
Gildas Bazin committed
160
    set_callbacks( OpenEncoder, CloseEncoder );
Gildas Bazin's avatar
Gildas Bazin committed
161 162 163 164 165 166 167

    add_integer( ENC_CFG_PREFIX "quality", 0, NULL, ENC_QUALITY_TEXT,
                 ENC_QUALITY_LONGTEXT, VLC_FALSE );
    add_integer( ENC_CFG_PREFIX "max-bitrate", 0, NULL, ENC_MAXBR_TEXT,
                 ENC_MAXBR_LONGTEXT, VLC_FALSE );
    add_integer( ENC_CFG_PREFIX "min-bitrate", 0, NULL, ENC_MINBR_TEXT,
                 ENC_MINBR_LONGTEXT, VLC_FALSE );
Gildas Bazin's avatar
 
Gildas Bazin committed
168 169
#endif

Gildas Bazin's avatar
 
Gildas Bazin committed
170 171
vlc_module_end();

172
#ifndef MODULE_NAME_IS_tremor
Gildas Bazin's avatar
Gildas Bazin committed
173 174 175
static const char *ppsz_enc_options[] = {
    "quality", "max-bitrate", "min-bitrate", NULL
};
176
#endif
Gildas Bazin's avatar
Gildas Bazin committed
177

Gildas Bazin's avatar
 
Gildas Bazin committed
178 179 180 181 182
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
Gildas Bazin's avatar
 
Gildas Bazin committed
183
    decoder_t *p_dec = (decoder_t*)p_this;
Gildas Bazin's avatar
 
Gildas Bazin committed
184
    decoder_sys_t *p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
185

Gildas Bazin's avatar
 
Gildas Bazin committed
186
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('v','o','r','b') )
Gildas Bazin's avatar
 
Gildas Bazin committed
187 188 189 190
    {
        return VLC_EGENERIC;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
191
    /* Allocate the memory needed to store the decoder's structure */
Gildas Bazin's avatar
 
Gildas Bazin committed
192
    if( ( p_dec->p_sys = p_sys =
Gildas Bazin's avatar
 
Gildas Bazin committed
193 194 195 196 197
          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220

    /* Misc init */
    aout_DateSet( &p_sys->end_date, 0 );
    p_sys->b_packetizer = VLC_FALSE;
    p_sys->i_headers = 0;

    /* Take care of vorbis init */
    vorbis_info_init( &p_sys->vi );
    vorbis_comment_init( &p_sys->vc );

    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
#ifdef MODULE_NAME_IS_tremor
    p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');
#else
    p_dec->fmt_out.i_codec = VLC_FOURCC('f','l','3','2');
#endif

    /* Set callbacks */
    p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
        DecodeBlock;
    p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
        DecodeBlock;
Gildas Bazin's avatar
 
Gildas Bazin committed
221

Gildas Bazin's avatar
 
Gildas Bazin committed
222 223 224
    return VLC_SUCCESS;
}

Gildas Bazin's avatar
 
Gildas Bazin committed
225 226 227 228 229 230
static int OpenPacketizer( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;

    int i_ret = OpenDecoder( p_this );

Gildas Bazin's avatar
 
Gildas Bazin committed
231 232 233 234 235
    if( i_ret == VLC_SUCCESS )
    {
        p_dec->p_sys->b_packetizer = VLC_TRUE;
        p_dec->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
236 237 238 239 240

    return i_ret;
}

/****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
241
 * DecodeBlock: the whole thing
Gildas Bazin's avatar
 
Gildas Bazin committed
242 243 244
 ****************************************************************************
 * This function must be fed with ogg packets.
 ****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
245
static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
Gildas Bazin's avatar
 
Gildas Bazin committed
246 247 248 249
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    ogg_packet oggpacket;

Gildas Bazin's avatar
 
Gildas Bazin committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
    if( !pp_block ) return NULL;

    if( *pp_block )
    {
        /* Block to Ogg packet */
        oggpacket.packet = (*pp_block)->p_buffer;
        oggpacket.bytes = (*pp_block)->i_buffer;
    }
    else
    {
        if( p_sys->b_packetizer ) return NULL;

        /* Block to Ogg packet */
        oggpacket.packet = NULL;
        oggpacket.bytes = 0;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
267
    oggpacket.granulepos = -1;
Gildas Bazin's avatar
 
Gildas Bazin committed
268 269 270 271 272
    oggpacket.b_o_s = 0;
    oggpacket.e_o_s = 0;
    oggpacket.packetno = 0;

    if( p_sys->i_headers == 0 )
273
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
274 275 276 277 278 279
        /* Take care of the initial Vorbis header */

        oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
        if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc,
                                       &oggpacket ) < 0 )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
280 281
            msg_Err( p_dec, "this bitstream does not contain Vorbis "
                     "audio data.");
Gildas Bazin's avatar
 
Gildas Bazin committed
282 283
            block_Release( *pp_block );
            return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
284 285 286
        }
        p_sys->i_headers++;

Gildas Bazin's avatar
 
Gildas Bazin committed
287 288 289 290 291 292
        /* Setup the format */
        p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;
        p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;
        p_dec->fmt_out.audio.i_physical_channels =
            p_dec->fmt_out.audio.i_original_channels =
                pi_channels_maps[p_sys->vi.channels];
Gildas Bazin's avatar
 
Gildas Bazin committed
293
        p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;
Gildas Bazin's avatar
 
Gildas Bazin committed
294

Gildas Bazin's avatar
 
Gildas Bazin committed
295
        aout_DateInit( &p_sys->end_date, p_sys->vi.rate );
Gildas Bazin's avatar
 
Gildas Bazin committed
296

Gildas Bazin's avatar
 
Gildas Bazin committed
297 298 299
        msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",
                 p_sys->vi.channels, p_sys->vi.rate,
                 p_sys->vi.bitrate_nominal );
Gildas Bazin's avatar
 
Gildas Bazin committed
300

Gildas Bazin's avatar
 
Gildas Bazin committed
301
        return ProcessPacket( p_dec, &oggpacket, pp_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
302 303
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
304
    if( p_sys->i_headers == 1 )
Gildas Bazin's avatar
 
Gildas Bazin committed
305
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
306 307 308 309 310
        /* The next packet in order is the comments header */
        if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
            < 0 )
        {
            msg_Err( p_dec, "2nd Vorbis header is corrupted" );
Gildas Bazin's avatar
 
Gildas Bazin committed
311 312
            block_Release( *pp_block );
            return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
313 314
        }
        p_sys->i_headers++;
Sam Hocevar's avatar
Sam Hocevar committed
315

Gildas Bazin's avatar
 
Gildas Bazin committed
316 317
        ParseVorbisComments( p_dec );

Gildas Bazin's avatar
 
Gildas Bazin committed
318
        return ProcessPacket( p_dec, &oggpacket, pp_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
319 320
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
321
    if( p_sys->i_headers == 2 )
Gildas Bazin's avatar
 
Gildas Bazin committed
322
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
323 324 325 326 327 328 329
        /* The next packet in order is the codebooks header
           We need to watch out that this packet is not missing as a
           missing or corrupted header is fatal. */
        if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket )
            < 0 )
        {
            msg_Err( p_dec, "3rd Vorbis header is corrupted" );
Gildas Bazin's avatar
 
Gildas Bazin committed
330 331
            block_Release( *pp_block );
            return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
332 333
        }
        p_sys->i_headers++;
Sam Hocevar's avatar
Sam Hocevar committed
334

Gildas Bazin's avatar
 
Gildas Bazin committed
335 336 337 338 339 340 341
        if( !p_sys->b_packetizer )
        {
            /* Initialize the Vorbis packet->PCM decoder */
            vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );
            vorbis_block_init( &p_sys->vd, &p_sys->vb );
        }

Gildas Bazin's avatar
 
Gildas Bazin committed
342
        return ProcessPacket( p_dec, &oggpacket, pp_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
343 344
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
345
    return ProcessPacket( p_dec, &oggpacket, pp_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
346
}
Gildas Bazin's avatar
 
Gildas Bazin committed
347

Gildas Bazin's avatar
 
Gildas Bazin committed
348 349 350
/*****************************************************************************
 * ProcessPacket: processes a Vorbis packet.
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
351 352
static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
                            block_t **pp_block )
Gildas Bazin's avatar
 
Gildas Bazin committed
353 354
{
    decoder_sys_t *p_sys = p_dec->p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
355
    block_t *p_block = *pp_block;
Gildas Bazin's avatar
 
Gildas Bazin committed
356

Gildas Bazin's avatar
 
Gildas Bazin committed
357
    /* Date management */
Gildas Bazin's avatar
 
Gildas Bazin committed
358 359
    if( p_block && p_block->i_pts > 0 &&
        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
360
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
361
        aout_DateSet( &p_sys->end_date, p_block->i_pts );
Gildas Bazin's avatar
 
Gildas Bazin committed
362 363
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
364 365 366
    if( !aout_DateGet( &p_sys->end_date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
Gildas Bazin's avatar
 
Gildas Bazin committed
367 368
        if( p_block ) block_Release( p_block );
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
369 370
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
371 372
    *pp_block = NULL; /* To avoid being fed the same packet again */

Gildas Bazin's avatar
 
Gildas Bazin committed
373 374
    if( p_sys->b_packetizer )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
375
        return SendPacket( p_dec, p_oggpacket, p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
376 377 378
    }
    else
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
379 380 381 382 383 384 385 386 387 388 389 390
        aout_buffer_t *p_aout_buffer;

        if( p_sys->i_headers >= 3 )
            p_aout_buffer = DecodePacket( p_dec, p_oggpacket );
        else
            p_aout_buffer = NULL;

        if( p_block )
        {
            block_Release( p_block );
        }
        return p_aout_buffer;
Gildas Bazin's avatar
 
Gildas Bazin committed
391
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
392 393 394 395 396
}

/*****************************************************************************
 * DecodePacket: decodes a Vorbis packet.
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
397
static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
Gildas Bazin's avatar
 
Gildas Bazin committed
398
{
Gildas Bazin's avatar
 
Gildas Bazin committed
399 400 401
    decoder_sys_t *p_sys = p_dec->p_sys;
    int           i_samples;

Gildas Bazin's avatar
 
Gildas Bazin committed
402 403 404
#ifdef MODULE_NAME_IS_tremor
    int32_t       **pp_pcm;
#else
Gildas Bazin's avatar
 
Gildas Bazin committed
405
    float         **pp_pcm;
Gildas Bazin's avatar
 
Gildas Bazin committed
406
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
407

Gildas Bazin's avatar
 
Gildas Bazin committed
408 409
    if( p_oggpacket->bytes &&
        vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
410
        vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );
Gildas Bazin's avatar
 
Gildas Bazin committed
411 412 413 414 415 416

    /* **pp_pcm is a multichannel float vector. In stereo, for
     * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is
     * the size of each channel. Convert the float values
     * (-1.<=range<=1.) to whatever PCM format and write it out */

Gildas Bazin's avatar
 
Gildas Bazin committed
417
    if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )
Gildas Bazin's avatar
 
Gildas Bazin committed
418 419
    {

Gildas Bazin's avatar
 
Gildas Bazin committed
420
        aout_buffer_t *p_aout_buffer;
Gildas Bazin's avatar
 
Gildas Bazin committed
421 422 423 424 425

        p_aout_buffer =
            p_dec->pf_aout_buffer_new( p_dec, i_samples );

        if( p_aout_buffer == NULL ) return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
426 427

        /* Interleave the samples */
Gildas Bazin's avatar
 
Gildas Bazin committed
428 429
#ifdef MODULE_NAME_IS_tremor
        Interleave( (int32_t *)p_aout_buffer->p_buffer,
Gildas Bazin's avatar
 
Gildas Bazin committed
430
                    (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
431 432
#else
        Interleave( (float *)p_aout_buffer->p_buffer,
Gildas Bazin's avatar
 
Gildas Bazin committed
433
                    (const float **)pp_pcm, p_sys->vi.channels, i_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
434
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
435 436

        /* Tell libvorbis how many samples we actually consumed */
Gildas Bazin's avatar
 
Gildas Bazin committed
437
        vorbis_synthesis_read( &p_sys->vd, i_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
438 439

        /* Date management */
Gildas Bazin's avatar
 
Gildas Bazin committed
440 441
        p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
        p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
Gildas Bazin's avatar
 
Gildas Bazin committed
442
                                                      i_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
443 444 445 446 447
        return p_aout_buffer;
    }
    else
    {
        return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
448 449 450 451
    }
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
452
 * SendPacket: send an ogg dated packet to the stream output.
Gildas Bazin's avatar
 
Gildas Bazin committed
453
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
454 455
static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
                            block_t *p_block )
Gildas Bazin's avatar
 
Gildas Bazin committed
456
{
Gildas Bazin's avatar
 
Gildas Bazin committed
457
    decoder_sys_t *p_sys = p_dec->p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
458
    int i_block_size, i_samples;
Gildas Bazin's avatar
 
Gildas Bazin committed
459

Gildas Bazin's avatar
 
Gildas Bazin committed
460 461 462 463
    i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );
    if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */
    i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
    p_sys->i_last_block_size = i_block_size;
Gildas Bazin's avatar
 
Gildas Bazin committed
464

Gildas Bazin's avatar
 
Gildas Bazin committed
465
    /* Date management */
Gildas Bazin's avatar
 
Gildas Bazin committed
466
    p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );
Gildas Bazin's avatar
 
Gildas Bazin committed
467 468

    if( p_sys->i_headers >= 3 )
Gildas Bazin's avatar
 
Gildas Bazin committed
469 470
        p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -
            p_block->i_pts;
Gildas Bazin's avatar
 
Gildas Bazin committed
471
    else
Gildas Bazin's avatar
 
Gildas Bazin committed
472
        p_block->i_length = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
473

Gildas Bazin's avatar
 
Gildas Bazin committed
474
    return p_block;
Gildas Bazin's avatar
 
Gildas Bazin committed
475 476
}

Gildas Bazin's avatar
 
Gildas Bazin committed
477 478 479 480 481 482 483 484 485 486 487 488 489
/*****************************************************************************
 * ParseVorbisComments: FIXME should be done in demuxer
 *****************************************************************************/
static void ParseVorbisComments( decoder_t *p_dec )
{
    input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
    int i = 0;
    char *psz_name, *psz_value, *psz_comment;
    while ( i < p_dec->p_sys->vc.comments )
    {
        psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );
        if( !psz_comment )
        {
Benjamin Pracht's avatar
Benjamin Pracht committed
490
            msg_Warn( p_dec, "out of memory" );
Gildas Bazin's avatar
 
Gildas Bazin committed
491 492 493 494 495 496 497 498
            break;
        }
        psz_name = psz_comment;
        psz_value = strchr( psz_comment, '=' );
        if( psz_value )
        {
            *psz_value = '\0';
            psz_value++;
499 500
            input_Control( p_input, INPUT_ADD_INFO, _("Vorbis comment"),
                           psz_name, psz_value );
Gildas Bazin's avatar
 
Gildas Bazin committed
501 502 503 504 505 506
        }
        free( psz_comment );
        i++;
    }
}

Gildas Bazin's avatar
 
Gildas Bazin committed
507 508 509
/*****************************************************************************
 * Interleave: helper function to interleave channels
 *****************************************************************************/
Sam Hocevar's avatar
Sam Hocevar committed
510
static void Interleave(
Gildas Bazin's avatar
 
Gildas Bazin committed
511
#ifdef MODULE_NAME_IS_tremor
Sam Hocevar's avatar
Sam Hocevar committed
512
                        int32_t *p_out, const int32_t **pp_in,
Gildas Bazin's avatar
 
Gildas Bazin committed
513
#else
Sam Hocevar's avatar
Sam Hocevar committed
514
                        float *p_out, const float **pp_in,
Gildas Bazin's avatar
 
Gildas Bazin committed
515 516
#endif
                        int i_nb_channels, int i_samples )
Gildas Bazin's avatar
 
Gildas Bazin committed
517 518 519 520 521
{
    int i, j;

    for ( j = 0; j < i_samples; j++ )
    {
522
        for ( i = 0; i < i_nb_channels; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
523
        {
524
            p_out[j * i_nb_channels + i] = pp_in[i][j];
Gildas Bazin's avatar
 
Gildas Bazin committed
525 526 527 528 529
        }
    }
}

/*****************************************************************************
Gildas Bazin's avatar
 
Gildas Bazin committed
530
 * CloseDecoder: vorbis decoder destruction
Gildas Bazin's avatar
 
Gildas Bazin committed
531
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin committed
532
static void CloseDecoder( vlc_object_t *p_this )
Gildas Bazin's avatar
 
Gildas Bazin committed
533
{
Gildas Bazin's avatar
 
Gildas Bazin committed
534
    decoder_t *p_dec = (decoder_t *)p_this;
Gildas Bazin's avatar
 
Gildas Bazin committed
535 536 537
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( !p_sys->b_packetizer && p_sys->i_headers >= 3 )
Gildas Bazin's avatar
 
Gildas Bazin committed
538
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
539 540
        vorbis_block_clear( &p_sys->vb );
        vorbis_dsp_clear( &p_sys->vd );
Gildas Bazin's avatar
 
Gildas Bazin committed
541
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
542 543 544 545 546

    vorbis_comment_clear( &p_sys->vc );
    vorbis_info_clear( &p_sys->vi );  /* must be called last */

    free( p_sys );
Gildas Bazin's avatar
 
Gildas Bazin committed
547
}
Gildas Bazin's avatar
 
Gildas Bazin committed
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573

#if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor)

/*****************************************************************************
 * encoder_sys_t : theora encoder descriptor
 *****************************************************************************/
struct encoder_sys_t
{
    /*
     * Input properties
     */
    int i_headers;

    /*
     * Vorbis properties
     */
    vorbis_info      vi; /* struct that stores all the static vorbis bitstream
                            settings */
    vorbis_comment   vc; /* struct that stores all the bitstream user
                          * comments */
    vorbis_dsp_state vd; /* central working state for the packet->PCM
                          * decoder */
    vorbis_block     vb; /* local working space for packet->PCM decode */

    int i_last_block_size;
    int i_samples_delay;
Gildas Bazin's avatar
 
Gildas Bazin committed
574
    int i_channels;
Gildas Bazin's avatar
 
Gildas Bazin committed
575 576 577 578 579 580 581 582 583 584 585 586 587

    /*
     * Common properties
     */
    mtime_t i_pts;
};

/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
Gildas Bazin's avatar
 
Gildas Bazin committed
588
    encoder_sys_t *p_sys;
Gildas Bazin's avatar
Gildas Bazin committed
589 590
    int i_quality, i_min_bitrate, i_max_bitrate;
    vlc_value_t val;
Gildas Bazin's avatar
 
Gildas Bazin committed
591

592 593
    if( p_enc->fmt_out.i_codec != VLC_FOURCC('v','o','r','b') &&
        !p_enc->b_force )
Gildas Bazin's avatar
 
Gildas Bazin committed
594 595 596 597 598 599 600 601 602 603 604 605 606 607
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
    {
        msg_Err( p_enc, "out of memory" );
        return VLC_EGENERIC;
    }
    p_enc->p_sys = p_sys;

    p_enc->pf_header = Headers;
    p_enc->pf_encode_audio = Encode;
Gildas Bazin's avatar
 
Gildas Bazin committed
608
    p_enc->fmt_in.i_codec = VLC_FOURCC('f','l','3','2');
609
    p_enc->fmt_out.i_codec = VLC_FOURCC('v','o','r','b');
Gildas Bazin's avatar
 
Gildas Bazin committed
610

Gildas Bazin's avatar
Gildas Bazin committed
611 612 613 614
    sout_ParseCfg( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    var_Get( p_enc, ENC_CFG_PREFIX "quality", &val );
    i_quality = val.i_int;
615 616
    if( i_quality > 10 ) i_quality = 10;
    if( i_quality < 0 ) i_quality = 0;
Gildas Bazin's avatar
Gildas Bazin committed
617 618 619 620 621
    var_Get( p_enc, ENC_CFG_PREFIX "max-bitrate", &val );
    i_max_bitrate = val.i_int;
    var_Get( p_enc, ENC_CFG_PREFIX "min-bitrate", &val );
    i_min_bitrate = val.i_int;

Gildas Bazin's avatar
 
Gildas Bazin committed
622 623 624
    /* Initialize vorbis encoder */
    vorbis_info_init( &p_sys->vi );

Gildas Bazin's avatar
Gildas Bazin committed
625
    if( i_quality > 0 )
Sam Hocevar's avatar
Sam Hocevar committed
626
    {
Gildas Bazin's avatar
Gildas Bazin committed
627 628 629
        /* VBR mode */
        if( vorbis_encode_setup_vbr( &p_sys->vi,
              p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
630
              i_quality * 0.1 ) )
Gildas Bazin's avatar
Gildas Bazin committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        {
            vorbis_info_clear( &p_sys->vi );
            free( p_enc->p_sys );
            msg_Err( p_enc, "VBR mode initialisation failed" );
            return VLC_EGENERIC;
        }

        /* Do we have optional hard quality restrictions? */
        if( i_max_bitrate > 0 || i_min_bitrate > 0 )
        {
            struct ovectl_ratemanage_arg ai;
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai );

            ai.bitrate_hard_min = i_min_bitrate;
            ai.bitrate_hard_max = i_max_bitrate;
            ai.management_active = 1;

            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai );

        }
        else
        {
            /* Turn off management entirely */
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL );
        }
Sam Hocevar's avatar
Sam Hocevar committed
656
    }
Gildas Bazin's avatar
Gildas Bazin committed
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672
    else
    {
        if( vorbis_encode_setup_managed( &p_sys->vi,
              p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
              i_min_bitrate > 0 ? i_min_bitrate * 1000: -1,
              p_enc->fmt_out.i_bitrate,
              i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) )
          {
              vorbis_info_clear( &p_sys->vi );
              msg_Err( p_enc, "CBR mode initialisation failed" );
              free( p_enc->p_sys );
              return VLC_EGENERIC;
          }
    }

    vorbis_encode_setup_init( &p_sys->vi );
Gildas Bazin's avatar
 
Gildas Bazin committed
673 674 675 676 677 678 679 680 681

    /* add a comment */
    vorbis_comment_init( &p_sys->vc);
    vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");

    /* set up the analysis state and auxiliary encoding storage */
    vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
    vorbis_block_init( &p_sys->vd, &p_sys->vb );

Gildas Bazin's avatar
 
Gildas Bazin committed
682
    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
Gildas Bazin's avatar
 
Gildas Bazin committed
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
    p_sys->i_last_block_size = 0;
    p_sys->i_samples_delay = 0;
    p_sys->i_headers = 0;
    p_sys->i_pts = 0;

    return VLC_SUCCESS;
}

/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out ogg packets.
 ****************************************************************************/
static block_t *Headers( encoder_t *p_enc )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
Gildas Bazin's avatar
 
Gildas Bazin committed
699
    block_t *p_block, *p_chain = NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

    /* Create theora headers */
    if( !p_sys->i_headers )
    {
        ogg_packet header[3];
        int i;

        vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
                                   &header[0], &header[1], &header[2]);
        for( i = 0; i < 3; i++ )
        {
            p_block = block_New( p_enc, header[i].bytes );
            memcpy( p_block->p_buffer, header[i].packet, header[i].bytes );

            p_block->i_dts = p_block->i_pts = p_block->i_length = 0;

Gildas Bazin's avatar
 
Gildas Bazin committed
716
            block_ChainAppend( &p_chain, p_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
717 718 719 720
        }
        p_sys->i_headers = 3;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
721
    return p_chain;
Gildas Bazin's avatar
 
Gildas Bazin committed
722 723 724 725 726 727 728 729 730 731 732 733 734
}

/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out ogg packets.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    ogg_packet oggpacket;
    block_t *p_block, *p_chain = NULL;
    float **buffer;
735 736
    int i;
    unsigned int j;
Gildas Bazin's avatar
 
Gildas Bazin committed
737 738 739

    p_sys->i_pts = p_aout_buf->start_date -
                (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
Gildas Bazin's avatar
 
Gildas Bazin committed
740
                (mtime_t)p_enc->fmt_in.audio.i_rate;
Gildas Bazin's avatar
 
Gildas Bazin committed
741

Gildas Bazin's avatar
 
Gildas Bazin committed
742
    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;
Gildas Bazin's avatar
 
Gildas Bazin committed
743

Gildas Bazin's avatar
 
Gildas Bazin committed
744
    buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
745 746

    /* convert samples to float and uninterleave */
Gildas Bazin's avatar
 
Gildas Bazin committed
747
    for( i = 0; i < p_sys->i_channels; i++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
748
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
749
        for( j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
Gildas Bazin's avatar
 
Gildas Bazin committed
750
        {
Gildas Bazin's avatar
 
Gildas Bazin committed
751 752
            buffer[i][j]= ((float)( ((int16_t *)p_aout_buf->p_buffer )
                                    [j * p_sys->i_channels + i ] )) / 32768.f;
Gildas Bazin's avatar
 
Gildas Bazin committed
753 754 755
        }
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
756
    vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
757 758 759

    while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
760 761
        int i_samples;

Gildas Bazin's avatar
 
Gildas Bazin committed
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
        vorbis_analysis( &p_sys->vb, NULL );
        vorbis_bitrate_addblock( &p_sys->vb );

        while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
        {
            int i_block_size;
            p_block = block_New( p_enc, oggpacket.bytes );
            memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );

            i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );

            if( i_block_size < 0 ) i_block_size = 0;
            i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
            p_sys->i_last_block_size = i_block_size;

            p_block->i_length = (mtime_t)1000000 *
Gildas Bazin's avatar
 
Gildas Bazin committed
778
                (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;
Gildas Bazin's avatar
 
Gildas Bazin committed
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

            p_block->i_dts = p_block->i_pts = p_sys->i_pts;

            p_sys->i_samples_delay -= i_samples;

            /* Update pts */
            p_sys->i_pts += p_block->i_length;
            block_ChainAppend( &p_chain, p_block );
        }
    }

    return p_chain;
}

/*****************************************************************************
 * CloseEncoder: theora encoder destruction
 *****************************************************************************/
static void CloseEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;

    vorbis_block_clear( &p_sys->vb );
    vorbis_dsp_clear( &p_sys->vd );
    vorbis_comment_clear( &p_sys->vc );
    vorbis_info_clear( &p_sys->vi );  /* must be called last */

    free( p_sys );
}

#endif /* HAVE_VORBIS_VORBISENC_H && !MODULE_NAME_IS_tremor */