Esempio n. 1
0
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
    double cfreq;

    if(avccontext->flags & CODEC_FLAG_QSCALE) {
        /* variable bitrate */
        if(vorbis_encode_setup_vbr(vi, avccontext->channels,
                avccontext->sample_rate,
                avccontext->global_quality / (float)FF_QP2LAMBDA))
            return -1;
    } else {
        /* constant bitrate */
        if(vorbis_encode_setup_managed(vi, avccontext->channels,
                avccontext->sample_rate, -1, avccontext->bit_rate, -1))
            return -1;

#ifdef OGGVORBIS_VBR_BY_ESTIMATE
        /* variable bitrate by estimate */
        if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL))
            return -1;
#endif
    }

    /* cutoff frequency */
    if(avccontext->cutoff > 0) {
        cfreq = avccontext->cutoff / 1000.0;
        if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
            return -1;
    }

    return vorbis_encode_setup_init(vi);
}
Esempio n. 2
0
static av_cold int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {
    double cfreq;

    if(avccontext->flags & CODEC_FLAG_QSCALE) {
        /* variable bitrate */
        if(vorbis_encode_setup_vbr(vi, avccontext->channels,
                avccontext->sample_rate,
                avccontext->global_quality / (float)FF_QP2LAMBDA / 10.0))
            return -1;
    } else {
        int minrate = avccontext->rc_min_rate > 0 ? avccontext->rc_min_rate : -1;
        int maxrate = avccontext->rc_min_rate > 0 ? avccontext->rc_max_rate : -1;

        /* constant bitrate */
        if(vorbis_encode_setup_managed(vi, avccontext->channels,
                avccontext->sample_rate, minrate, avccontext->bit_rate, maxrate))
            return -1;

        /* variable bitrate by estimate, disable slow rate management */
        if(minrate == -1 && maxrate == -1)
            if(vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE2_SET, NULL))
                return -1;
    }

    /* cutoff frequency */
    if(avccontext->cutoff > 0) {
        cfreq = avccontext->cutoff / 1000.0;
        if(vorbis_encode_ctl(vi, OV_ECTL_LOWPASS_SET, &cfreq))
            return -1;
    }

    return vorbis_encode_setup_init(vi);
}
Esempio n. 3
0
 void init() {
   vorbis_info_init(&settings);
   THROW_IF(vorbis_encode_setup_managed(&settings, channels, sample_rate, -1, bitrate, -1) != 0, Invalid);
   THROW_IF(vorbis_encode_ctl(&settings, OV_ECTL_RATEMANAGE2_SET, NULL) != 0, Invalid);
   THROW_IF(vorbis_encode_setup_init(&settings) != 0, Invalid);
   THROW_IF(vorbis_analysis_init(&dsp_state, &settings) != 0, Invalid);
   vorbis_comment_init(&comment);
   vorbis_block_init(&dsp_state, &block);
 }
Esempio n. 4
0
static int oggvorbis_init_encoder(vorbis_info *vi, AVCodecContext *avccontext) {

#ifdef OGGVORBIS_VBR_BY_ESTIMATE
    /* variable bitrate by estimate */

    return (vorbis_encode_setup_managed(vi, avccontext->channels,
              avccontext->sample_rate, -1, avccontext->bit_rate, -1) ||
	    vorbis_encode_ctl(vi, OV_ECTL_RATEMANAGE_AVG, NULL) ||
	    vorbis_encode_setup_init(vi)) ;
#else
    /* constant bitrate */

    return vorbis_encode_init(vi, avccontext->channels,
	          avccontext->sample_rate, -1, avccontext->bit_rate, -1) ;
#endif
}
int vorbis_encode_init(vorbis_info *vi,
		       long channels,
		       long rate,

		       long max_bitrate,
		       long nominal_bitrate,
		       long min_bitrate){

  int ret=vorbis_encode_setup_managed(vi,channels,rate,
				      max_bitrate,
				      nominal_bitrate,
				      min_bitrate);
  if(ret){
    vorbis_info_clear(vi);
    return(ret);
  }

  ret=vorbis_encode_setup_init(vi);
  if(ret)
    vorbis_info_clear(vi);
  return(ret);
}
Esempio n. 6
0
static int
vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
{	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
	int k, ret ;

	vorbis_info_init (&vdata->vinfo) ;

	/* The style of encoding should be selectable here, VBR quality mode. */
	ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;

#if 0
	ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */
	ret = (	vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1)
					|| vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL)
					|| vorbis_encode_setup_init (&vdata->vinfo)
				) ;
#endif
	if (ret)
		return SFE_BAD_OPEN_FORMAT ;

	vdata->loc = 0 ;

	/* add a comment */
	vorbis_comment_init (&vdata->vcomment) ;

	vorbis_comment_add_tag (&vdata->vcomment, "ENCODER", "libsndfile") ;
	for (k = 0 ; k < SF_MAX_STRINGS ; k++)
	{	const char * name ;

		if (psf->strings.data [k].type == 0)
			break ;

		switch (psf->strings.data [k].type)
		{	case SF_STR_TITLE :
				name = "TITLE" ;
				break ;
			case SF_STR_COPYRIGHT :
				name = "COPYRIGHT" ;
				break ;
			case SF_STR_SOFTWARE :
				name = "SOFTWARE" ;
				break ;
			case SF_STR_ARTIST :
				name = "ARTIST" ;
				break ;
			case SF_STR_COMMENT :
				name = "COMMENT" ;
				break ;
			case SF_STR_DATE :
				name = "DATE" ;
				break ;
			case SF_STR_ALBUM :
				name = "ALBUM" ;
				break ;
			case SF_STR_LICENSE :
				name = "LICENSE" ;
				break ;
			case SF_STR_TRACKNUMBER :
				name = "Tracknumber" ;
				break ;
			case SF_STR_GENRE :
				name = "Genre" ;
				break ;

			default :
				continue ;
		} ;

		vorbis_comment_add_tag (&vdata->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ;
	} ;

	/* set up the analysis state and auxiliary encoding storage */
	vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ;
	vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;

	/*
	**	Set up our packet->stream encoder.
	**	Pick a random serial number ; that way we can more likely build
	**	chained streams just by concatenation.
	*/

	ogg_stream_init (&odata->ostream, psf_rand_int32 ()) ;

	/* Vorbis streams begin with three headers ; the initial header (with
	   most of the codec setup parameters) which is mandated by the Ogg
	   bitstream spec.  The second header holds any comment fields.	 The
	   third header holds the bitstream codebook.  We merely need to
	   make the headers, then pass them to libvorbis one at a time ;
	   libvorbis handles the additional Ogg bitstream constraints */

	{	ogg_packet header ;
		ogg_packet header_comm ;
		ogg_packet header_code ;
		int result ;

		vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
		ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
		ogg_stream_packetin (&odata->ostream, &header_comm) ;
		ogg_stream_packetin (&odata->ostream, &header_code) ;

		/* This ensures the actual
		 * audio data will start on a new page, as per spec
		 */
		while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
		{	psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
			psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
		} ;
	}

	return 0 ;
} /* vorbis_write_header */
Esempio n. 7
0
// Just create the Quicktime objects since this routine is also called
// for reopening.
int FileVorbis::open_file(int rd, int wr)
{
	int result = 0;
	this->rd = rd;
	this->wr = wr;

//printf("FileVorbis::open_file 1\n");
	if(rd)
	{
//printf("FileVorbis::open_file 1\n");
		if(!(fd = fopen(asset->path, "rb")))
		{
			eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
			result = 1;
		}
		else
		{
//printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
			if(ov_open(fd, &vf, NULL, 0) < 0)
			{
				eprintf("Invalid bitstream in %s\n", asset->path);
				result = 1;
			}
			else
			{
//printf("FileVorbis::open_file 1\n");
				vorbis_info *vi = ov_info(&vf, -1);
				asset->channels = vi->channels;
				if(!asset->sample_rate)
					asset->sample_rate = vi->rate;
//printf("FileVorbis::open_file 1\n");
				asset->audio_length = ov_pcm_total(&vf,-1);
//printf("FileVorbis::open_file 1\n");
				asset->audio_data = 1;
// printf("FileVorbis::open_file 1 %d %d %d\n", 
// asset->channels, 
// asset->sample_rate, 
// asset->audio_length);
			}
		}
	}

	if(wr)
	{
		if(!(fd = fopen(asset->path, "wb")))
		{
			eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
			result = 1;
		}
		else
		{
			vorbis_info_init(&vi);
			if(!asset->vorbis_vbr)
				result = vorbis_encode_init(&vi, 
					asset->channels, 
					asset->sample_rate, 
					asset->vorbis_max_bitrate, 
					asset->vorbis_bitrate, 
					asset->vorbis_min_bitrate);
			else
			{
				result = vorbis_encode_setup_managed(&vi,
					asset->channels, 
					asset->sample_rate, 
					asset->vorbis_max_bitrate, 
					asset->vorbis_bitrate, 
					asset->vorbis_min_bitrate);
				result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
				result |= vorbis_encode_setup_init(&vi);
			}

			if(!result)
			{
				vorbis_analysis_init(&vd, &vi);
				vorbis_block_init(&vd, &vb);
				vorbis_comment_init(&vc);
				srand(time(NULL));
				ogg_stream_init(&os, rand());

				ogg_packet header;
				ogg_packet header_comm;
				ogg_packet header_code;
				vorbis_analysis_headerout(&vd, 
					&vc,
					&header,
					&header_comm,
					&header_code);
				ogg_stream_packetin(&os,
					&header);
				ogg_stream_packetin(&os, 
					&header_comm);
				ogg_stream_packetin(&os,
					&header_code);

				while(1)
				{
					int result = ogg_stream_flush(&os, &og);
					if(result == 0) break;
					fwrite(og.header, 1, og.header_len, fd);
					fwrite(og.body, 1, og.body_len, fd);
				}
			}
		}
	}

//printf("FileVorbis::open_file 2\n");
	return result;
}
Esempio n. 8
0
/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    int i_quality, i_min_bitrate, i_max_bitrate;
    ogg_packet header[3];

    if( p_enc->fmt_out.i_codec != VLC_CODEC_VORBIS &&
            !p_enc->b_force )
    {
        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 )
        return VLC_ENOMEM;
    p_enc->p_sys = p_sys;

    p_enc->pf_encode_audio = Encode;
    p_enc->fmt_in.i_codec  = VLC_CODEC_FL32;
    p_enc->fmt_out.i_codec = VLC_CODEC_VORBIS;

    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
    if( i_quality > 10 ) i_quality = 10;
    if( i_quality < 0 ) i_quality = 0;

    if( var_GetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ) i_quality = 0;
    i_max_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "max-bitrate" );
    i_min_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "min-bitrate" );

    /* Initialize vorbis encoder */
    vorbis_info_init( &p_sys->vi );

    if( i_quality > 0 )
    {
        /* VBR mode */
        if( vorbis_encode_setup_vbr( &p_sys->vi,
                                     p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
                                     i_quality * 0.1 ) )
        {
            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 );
        }
    }
    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 );

    /* 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 );

    /* Create and store headers */
    vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
                               &header[0], &header[1], &header[2]);
    for( int i = 0; i < 3; i++ )
    {
        if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra, &p_enc->fmt_out.p_extra,
                                header[i].bytes, header[i].packet ) )
        {
            p_enc->fmt_out.i_extra = 0;
            p_enc->fmt_out.p_extra = NULL;
        }
    }

    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
    p_sys->i_last_block_size = 0;
    p_sys->i_samples_delay = 0;

    ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
                          p_enc->fmt_in.audio.i_physical_channels, true);

    return VLC_SUCCESS;
}
static gboolean
gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc)
{

  GST_LOG_OBJECT (vorbisenc, "setup");

  if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0
      && vorbisenc->max_bitrate < 0) {
    vorbisenc->quality_set = TRUE;
  }

  update_start_message (vorbisenc);

  /* choose an encoding mode */
  /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
  vorbis_info_init (&vorbisenc->vi);

  if (vorbisenc->quality_set) {
    if (vorbis_encode_setup_vbr (&vorbisenc->vi,
            vorbisenc->channels, vorbisenc->frequency,
            vorbisenc->quality) != 0) {
      GST_ERROR_OBJECT (vorbisenc,
          "vorbisenc: initialisation failed: invalid parameters for quality");
      vorbis_info_clear (&vorbisenc->vi);
      return FALSE;
    }

    /* do we have optional hard quality restrictions? */
    if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) {
      struct ovectl_ratemanage_arg ai;

      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai);

      ai.bitrate_hard_min = vorbisenc->min_bitrate;
      ai.bitrate_hard_max = vorbisenc->max_bitrate;
      ai.management_active = 1;

      vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai);
    }
  } else {
    long min_bitrate, max_bitrate;

    min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1;
    max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1;

    if (vorbis_encode_setup_managed (&vorbisenc->vi,
            vorbisenc->channels,
            vorbisenc->frequency,
            max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) {
      GST_ERROR_OBJECT (vorbisenc,
          "vorbis_encode_setup_managed "
          "(c %d, rate %d, max br %ld, br %d, min br %ld) failed",
          vorbisenc->channels, vorbisenc->frequency, max_bitrate,
          vorbisenc->bitrate, min_bitrate);
      vorbis_info_clear (&vorbisenc->vi);
      return FALSE;
    }
  }

  if (vorbisenc->managed && vorbisenc->bitrate < 0) {
    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL);
  } else if (!vorbisenc->managed) {
    /* Turn off management entirely (if it was turned on). */
    vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL);
  }
  vorbis_encode_setup_init (&vorbisenc->vi);

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

  /* samples == granulepos start at 0 again */
  vorbisenc->samples_out = 0;

  /* fresh encoder available */
  vorbisenc->setup = TRUE;

  return TRUE;
}
Esempio n. 10
0
int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
{
    hb_audio_t * audio = w->audio;
    int i;
    ogg_packet header[3];

    hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
    w->private_data = pv;
    pv->out_discrete_channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown);

    pv->job   = job;

    hb_log( "encvorbis: opening libvorbis" );

    /* init */
    for( i = 0; i < 3; i++ )
    {
        // Zero vorbis headers so that we don't crash in mk_laceXiph
        // when vorbis_encode_setup_managed fails.
        memset( w->config->vorbis.headers[i], 0, sizeof( ogg_packet ) );
    }
    vorbis_info_init( &pv->vi );

    if( audio->config.out.bitrate > 0 )
    {
        /* 28kbps/channel seems to be the minimum for 6ch vorbis. */
        int min_bitrate = 28 * pv->out_discrete_channels;
        if (pv->out_discrete_channels > 2 && audio->config.out.bitrate < min_bitrate)
        {
            hb_log( "encvorbis: Selected bitrate (%d kbps) too low for %d channel audio.", audio->config.out.bitrate, pv->out_discrete_channels);
            hb_log( "encvorbis: Resetting bitrate to %d kbps", min_bitrate);
            /* Naughty! We shouldn't modify the audio from here. */
            audio->config.out.bitrate = min_bitrate;
        }

        if( vorbis_encode_setup_managed( &pv->vi, pv->out_discrete_channels,
              audio->config.out.samplerate, -1, 1000 * audio->config.out.bitrate, -1 ) )
        {
            hb_error( "encvorbis: vorbis_encode_setup_managed failed.\n" );
            *job->die = 1;
            return -1;
        }
    }
    else if( audio->config.out.quality != -1 )
    {
        // map VBR quality to Vorbis API (divide by 10)
        if( vorbis_encode_setup_vbr( &pv->vi, pv->out_discrete_channels,
              audio->config.out.samplerate, audio->config.out.quality/10 ) )
        {
            hb_error( "encvorbis: vorbis_encode_setup_vbr failed.\n" );
            *job->die = 1;
            return -1;
        }
    }

    if( vorbis_encode_ctl( &pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL ) ||
          vorbis_encode_setup_init( &pv->vi ) )
    {
        hb_error( "encvorbis: vorbis_encode_ctl( ratemanage2_set ) OR vorbis_encode_setup_init failed.\n" );
        *job->die = 1;
        return -1;
    }

    /* add a comment */
    vorbis_comment_init( &pv->vc );
    vorbis_comment_add_tag( &pv->vc, "Encoder", "HandBrake");
    vorbis_comment_add_tag( &pv->vc, "LANGUAGE", w->config->vorbis.language);

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

    /* get the 3 headers */
    vorbis_analysis_headerout( &pv->vd, &pv->vc,
                               &header[0], &header[1], &header[2] );
    for( i = 0; i < 3; i++ )
    {
        memcpy( w->config->vorbis.headers[i], &header[i],
                sizeof( ogg_packet ) );
        memcpy( w->config->vorbis.headers[i] + sizeof( ogg_packet ),
                header[i].packet, header[i].bytes );
    }

    pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
    audio->config.out.samples_per_frame = OGGVORBIS_FRAME_SIZE;
    pv->buf = malloc( pv->input_samples * sizeof( float ) );

    pv->list = hb_list_init();

    switch (pv->out_discrete_channels) {
        case 1:
            pv->channel_map[0] = 0;
            break;
        case 6:
            // Vorbis uses the following channel map = L C R Ls Rs Lfe
            if( audio->config.in.channel_map == &hb_ac3_chan_map )
            {
                pv->channel_map[0] = 1;
                pv->channel_map[1] = 2;
                pv->channel_map[2] = 3;
                pv->channel_map[3] = 4;
                pv->channel_map[4] = 5;
                pv->channel_map[5] = 0;
            }
            else if( audio->config.in.channel_map == &hb_smpte_chan_map )
            {
                pv->channel_map[0] = 0;
                pv->channel_map[1] = 2;
                pv->channel_map[2] = 1;
                pv->channel_map[3] = 4;
                pv->channel_map[4] = 5;
                pv->channel_map[5] = 3;
            }
            else // &hb_qt_chan_map
            {
                pv->channel_map[0] = 1;
                pv->channel_map[1] = 0;
                pv->channel_map[2] = 2;
                pv->channel_map[3] = 3;
                pv->channel_map[4] = 4;
                pv->channel_map[5] = 5;
            }
            break;
        default:
            hb_log("encvorbis.c: Unable to correctly proccess %d channels, assuming stereo.", pv->out_discrete_channels);
        case 2:
            // Assume stereo
            pv->channel_map[0] = 0;
            pv->channel_map[1] = 1;
            break;
    }

    return 0;
}
Esempio n. 11
0
void CompressionTool::encodeRaw(const char *rawData, int length, int samplerate, const char *outname, AudioFormat compmode) {

	print(" - len=%ld, ch=%d, rate=%d, %dbits", length, (rawAudioType.isStereo ? 2 : 1), samplerate, rawAudioType.bitsPerSample);

#ifdef USE_VORBIS
	if (compmode == AUDIO_VORBIS) {
		char outputString[256] = "";
		int numChannels = (rawAudioType.isStereo ? 2 : 1);
		int totalSamples = length / ((rawAudioType.bitsPerSample / 8) * numChannels);
		int samplesLeft = totalSamples;
		int eos = 0;
		int totalBytes = 0;

		vorbis_info vi;
		vorbis_comment vc;
		vorbis_dsp_state vd;
		vorbis_block vb;

		ogg_stream_state os;
		ogg_page og;
		ogg_packet op;

		ogg_packet header;
		ogg_packet header_comm;
		ogg_packet header_code;

		Common::File outputOgg(outname, "wb");

		vorbis_info_init(&vi);

		if (oggparms.nominalBitr > 0) {
			int result = 0;

			/* Input is in kbps, function takes bps */
			result = vorbis_encode_setup_managed(&vi, numChannels, samplerate, (oggparms.maxBitr > 0 ? 1000 * oggparms.maxBitr : -1), (1000 * oggparms.nominalBitr), (oggparms.minBitr > 0 ? 1000 * oggparms.minBitr : -1));

			if (result == OV_EFAULT) {
				vorbis_info_clear(&vi);
				error("Error: Internal Logic Fault");
			} else if ((result == OV_EINVAL) || (result == OV_EIMPL)) {
				vorbis_info_clear(&vi);
				error("Error: Invalid bitrate parameters");
			}

			if (!oggparms.silent) {
				sprintf(outputString, "Encoding to\n         \"%s\"\nat average bitrate %i kbps (", outname, oggparms.nominalBitr);

				if (oggparms.minBitr > 0) {
					sprintf(outputString + strlen(outputString), "min %i kbps, ", oggparms.minBitr);
				} else {
					sprintf(outputString + strlen(outputString), "no min, ");
				}

				if (oggparms.maxBitr > 0) {
					sprintf(outputString + strlen(outputString), "max %i kbps),\nusing full bitrate management engine\nSet optional hard quality restrictions\n", oggparms.maxBitr);
				} else {
					sprintf(outputString + strlen(outputString), "no max),\nusing full bitrate management engine\nSet optional hard quality restrictions\n");
				}
			}
		} else {
			int result = 0;

			/* Quality input is -1 - 10, function takes -0.1 through 1.0 */
			result = vorbis_encode_setup_vbr(&vi, numChannels, samplerate, oggparms.quality * 0.1f);

			if (result == OV_EFAULT) {
				vorbis_info_clear(&vi);
				error("Internal Logic Fault");
			} else if ((result == OV_EINVAL) || (result == OV_EIMPL)) {
				vorbis_info_clear(&vi);
				error("Invalid bitrate parameters");
			}

			if (!oggparms.silent) {
				sprintf(outputString, "Encoding to\n         \"%s\"\nat quality %2.2f", outname, oggparms.quality);
			}

			if ((oggparms.minBitr > 0) || (oggparms.maxBitr > 0)) {
				struct ovectl_ratemanage_arg extraParam;
				vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_GET, &extraParam);

				extraParam.bitrate_hard_min = (oggparms.minBitr > 0 ? (1000 * oggparms.minBitr) : -1);
				extraParam.bitrate_hard_max = (oggparms.maxBitr > 0 ? (1000 * oggparms.maxBitr) : -1);
				extraParam.management_active = 1;

				vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_SET, &extraParam);

				if (!oggparms.silent) {
					sprintf(outputString + strlen(outputString), " using constrained VBR (");

					if (oggparms.minBitr != -1) {
						sprintf(outputString + strlen(outputString), "min %i kbps, ", oggparms.minBitr);
					} else {
						sprintf(outputString + strlen(outputString), "no min, ");
					}

					if (oggparms.maxBitr != -1) {
						sprintf(outputString + strlen(outputString), "max %i kbps)\nSet optional hard quality restrictions\n", oggparms.maxBitr);
					} else {
						sprintf(outputString + strlen(outputString), "no max)\nSet optional hard quality restrictions\n");
					}
				}
			} else {
				sprintf(outputString + strlen(outputString), "\n");
			}
		}

		puts(outputString);

		vorbis_encode_setup_init(&vi);
		vorbis_comment_init(&vc);
		vorbis_analysis_init(&vd, &vi);
		vorbis_block_init(&vd, &vb);
		ogg_stream_init(&os, 0);
		vorbis_analysis_headerout(&vd, &vc, &header, &header_comm, &header_code);

		ogg_stream_packetin(&os, &header);
		ogg_stream_packetin(&os, &header_comm);
		ogg_stream_packetin(&os, &header_code);

		while (!eos) {
			int result = ogg_stream_flush(&os,&og);

			if (result == 0) {
				break;
			}

			outputOgg.write(og.header, og.header_len);
			outputOgg.write(og.body, og.body_len);
		}

		while (!eos) {
			int numSamples = ((samplesLeft < 2048) ? samplesLeft : 2048);
			float **buffer = vorbis_analysis_buffer(&vd, numSamples);

			/* We must tell the encoder that we have reached the end of the stream */
			if (numSamples == 0) {
				vorbis_analysis_wrote(&vd, 0);
			} else {
				/* Adapted from oggenc 1.1.1 */
				if (rawAudioType.bitsPerSample == 8) {
					const byte *rawDataUnsigned = (const byte *)rawData;
					for (int i = 0; i < numSamples; i++) {
						for (int j = 0; j < numChannels; j++) {
							buffer[j][i] = ((int)(rawDataUnsigned[i * numChannels + j]) - 128) / 128.0f;
						}
					}
				} else if (rawAudioType.bitsPerSample == 16) {
					if (rawAudioType.isLittleEndian) {
						for (int i = 0; i < numSamples; i++) {
							for (int j = 0; j < numChannels; j++) {
								buffer[j][i] = ((rawData[(i * 2 * numChannels) + (2 * j) + 1] << 8) | (rawData[(i * 2 * numChannels) + (2 * j)] & 0xff)) / 32768.0f;
							}
						}
					} else {
						for (int i = 0; i < numSamples; i++) {
							for (int j = 0; j < numChannels; j++) {
								buffer[j][i] = ((rawData[(i * 2 * numChannels) + (2 * j)] << 8) | (rawData[(i * 2 * numChannels) + (2 * j) + 1] & 0xff)) / 32768.0f;
							}
						}
					}
				}

				vorbis_analysis_wrote(&vd, numSamples);
			}

			while (vorbis_analysis_blockout(&vd, &vb) == 1) {
				vorbis_analysis(&vb, NULL);
				vorbis_bitrate_addblock(&vb);

				while (vorbis_bitrate_flushpacket(&vd, &op)) {
					ogg_stream_packetin(&os, &op);

					while (!eos) {
						int result = ogg_stream_pageout(&os, &og);

						if (result == 0) {
							break;
						}

						totalBytes += outputOgg.write(og.header, og.header_len);
						totalBytes += outputOgg.write(og.body, og.body_len);

						if (ogg_page_eos(&og)) {
							eos = 1;
						}
					}
				}
			}

			rawData += 2048 * (rawAudioType.bitsPerSample / 8) * numChannels;
			samplesLeft -= 2048;
		}

		ogg_stream_clear(&os);
		vorbis_block_clear(&vb);
		vorbis_dsp_clear(&vd);
		vorbis_info_clear(&vi);

		if (!oggparms.silent) {
			print("\nDone encoding file \"%s\"", outname);
			print("\n\tFile length:  %dm %ds", (int)(totalSamples / samplerate / 60), (totalSamples / samplerate % 60));
			print("\tAverage bitrate: %.1f kb/s\n", (8.0 * (double)totalBytes / 1000.0) / ((double)totalSamples / (double)samplerate));
		}
	}
#endif

#ifdef USE_FLAC
	if (compmode == AUDIO_FLAC) {
		int i;
		int numChannels = (rawAudioType.isStereo ? 2 : 1);
		int samplesPerChannel = length / ((rawAudioType.bitsPerSample / 8) * numChannels);
		FLAC__StreamEncoder *encoder;
		FLAC__StreamEncoderInitStatus initStatus;
		FLAC__int32 *flacData;

		flacData = (FLAC__int32 *)malloc(samplesPerChannel * numChannels * sizeof(FLAC__int32));

		if (rawAudioType.bitsPerSample == 8) {
			for (i = 0; i < samplesPerChannel * numChannels; i++) {
				FLAC__uint8 *rawDataUnsigned;
				rawDataUnsigned = (FLAC__uint8 *)rawData;
				flacData[i] = (FLAC__int32)rawDataUnsigned[i] - 0x80;
			}
		} else if (rawAudioType.bitsPerSample == 16) {
			/* The rawData pointer is an 8-bit char so we must create a new pointer to access 16-bit samples */
			FLAC__int16 *rawData16;
			rawData16 = (FLAC__int16 *)rawData;
			for (i = 0; i < samplesPerChannel * numChannels; i++) {
				flacData[i] = (FLAC__int32)rawData16[i];
			}
		}

		if (!flacparms.silent) {
			print("Encoding to\n         \"%s\"\nat compression level %d using blocksize %d\n", outname, flacparms.compressionLevel, flacparms.blocksize);
		}

		encoder = FLAC__stream_encoder_new();

		FLAC__stream_encoder_set_bits_per_sample(encoder, rawAudioType.bitsPerSample);
		FLAC__stream_encoder_set_blocksize(encoder, flacparms.blocksize);
		FLAC__stream_encoder_set_channels(encoder, numChannels);
		FLAC__stream_encoder_set_compression_level(encoder, flacparms.compressionLevel);
		FLAC__stream_encoder_set_sample_rate(encoder, samplerate);
		FLAC__stream_encoder_set_streamable_subset(encoder, false);
		FLAC__stream_encoder_set_total_samples_estimate(encoder, samplesPerChannel);
		FLAC__stream_encoder_set_verify(encoder, flacparms.verify);

		initStatus = FLAC__stream_encoder_init_file(encoder, outname, NULL, NULL);

		if (initStatus != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
			char buf[2048];
			sprintf(buf, "Error in FLAC encoder. (check the parameters)\nExact error was:%s", FLAC__StreamEncoderInitStatusString[initStatus]);
			free(flacData);
			throw ToolException(buf);
		} else {
			FLAC__stream_encoder_process_interleaved(encoder, flacData, samplesPerChannel);
		}

		FLAC__stream_encoder_finish(encoder);
		FLAC__stream_encoder_delete(encoder);

		free(flacData);

		if (!flacparms.silent) {
			print("\nDone encoding file \"%s\"", outname);
			print("\n\tFile length:  %dm %ds\n", (int)(samplesPerChannel / samplerate / 60), (samplesPerChannel / samplerate % 60));
		}
	}
#endif
}
Esempio n. 12
0
static int encode_ogg (cdrom_drive *drive, rip_opts_s *rip_opts,
		       text_tag_s *text_tag, int track,
		       int tracktot, char *filename, char **filenames)
{
  ogg_stream_state os;
  ogg_page og;
  ogg_packet op;

  vorbis_dsp_state vd;
  vorbis_block vb;
  vorbis_info vi;

  long samplesdone = 0;
  int sector = 0, last_sector = 0;
  long bytes_written = 0, packetsdone = 0;
  double time_elapsed = 0.0;
  int ret = 0;
  time_t *timer;
  double time;
  
  int serialno = rand ();
  vorbis_comment vc;
  long total_samples_per_channel = 0;
  int channels = 2;
  int eos = 0;
  long rate = 44100;
  FILE *out = fopen (filename, "w+");

  timer = timer_start ();

  if (!rip_opts->managed && (rip_opts->min_bitrate > 0 || rip_opts->max_bitrate > 0)) {
    log_msg ("Min or max bitrate requires managed", FL, FN, LN);
    return -1;
  }

  if (rip_opts->bitrate < 0 && rip_opts->min_bitrate < 0 && rip_opts->max_bitrate < 0) {
    rip_opts->quality_set = 1;
  }
  
  start_func (filename, rip_opts->bitrate, rip_opts->quality, rip_opts->quality_set,
	      rip_opts->managed, rip_opts->min_bitrate, rip_opts->max_bitrate);
  
  vorbis_info_init (&vi);

  if (rip_opts->quality_set > 0) {
    if (vorbis_encode_setup_vbr (&vi, channels, rate, rip_opts->quality)) {
      log_msg ("Couldn't initialize vorbis_info", FL, FN, LN);
      vorbis_info_clear (&vi);
      return -1;
    }
    /* two options here, max or min bitrate */
    if (rip_opts->max_bitrate > 0 || rip_opts->min_bitrate > 0) {
      struct ovectl_ratemanage_arg ai;
      vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_GET, &ai);
      ai.bitrate_hard_min = rip_opts->min_bitrate;
      ai.bitrate_hard_max = rip_opts->max_bitrate;
      ai.management_active = 1;
      vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_SET, &ai);
    }
  } else {
    if (vorbis_encode_setup_managed (&vi, channels, rate,
				     rip_opts->max_bitrate > 0 ? rip_opts->max_bitrate * 1000 : -1,
				     rip_opts->bitrate * 1000,
				     rip_opts->min_bitrate > 0 ? rip_opts->min_bitrate * 1000 : -1)) {
      log_msg ("Mode init failed, encode setup managed", FL, FN, LN);
      vorbis_info_clear (&vi);
      return -1;
    }
  }

  if (rip_opts->managed && rip_opts->bitrate < 0) {
    vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
  } else if (!rip_opts->managed) {
    vorbis_encode_ctl (&vi, OV_ECTL_RATEMANAGE_SET, NULL);
  }

  /* set advanced encoder options */

  vorbis_encode_setup_init (&vi);

  vorbis_analysis_init (&vd, &vi);
  vorbis_block_init (&vd, &vb);

  ogg_stream_init (&os, serialno);

  {
    ogg_packet header_main;
    ogg_packet header_comments;
    ogg_packet header_codebooks;
    int result;
    char buf[32];

    vorbis_comment_init (&vc);
    vorbis_comment_add_tag (&vc, "title", text_tag->songname);
    vorbis_comment_add_tag (&vc, "artist", text_tag->artistname);
    vorbis_comment_add_tag (&vc, "album", text_tag->albumname);
    vorbis_comment_add_tag (&vc, "genre", text_tag->genre);
    snprintf (buf, 32, "%d", text_tag->year);
    vorbis_comment_add_tag (&vc, "date", buf);
    snprintf (buf, 32, "%02d", text_tag->track);
    vorbis_comment_add_tag (&vc, "tracknumber", buf);
	
    vorbis_analysis_headerout (&vd, &vc, &header_main, &header_comments, &header_codebooks);

    ogg_stream_packetin (&os, &header_main);
    ogg_stream_packetin (&os, &header_comments);
    ogg_stream_packetin (&os, &header_codebooks);

    while ((result = ogg_stream_flush (&os, &og))) {
      if (result == 0)
	break;
      ret = write_page (&og, out);
      if (ret != og.header_len + og.body_len) {
	log_msg ("Failed writing data to output stream", FL, FN, LN);
	ret = -1;
      }
    }
	  
    sector = cdda_track_firstsector (drive, track);
    last_sector = cdda_track_lastsector (drive, track);
    total_samples_per_channel = (last_sector - sector) * (CD_FRAMESAMPLES / 2);
    int eos = 0;
	
    while (!eos) {
      signed char *buffer = (signed char *)malloc (CD_FRAMESIZE_RAW * READ_SECTORS);
      //use this variable as a s**t
      long sectors_read = last_sector - sector;
      if (sectors_read > READ_SECTORS)
	sectors_read = READ_SECTORS;

      sectors_read = cdda_read (drive, (signed char *)buffer, sector, sectors_read);
      int i;
	  
      if (sectors_read == 0) {
	vorbis_analysis_wrote (&vd, 0);
      } else {
	float **vorbbuf = vorbis_analysis_buffer (&vd, CD_FRAMESIZE_RAW * sectors_read);
	for (i = 0; i < (CD_FRAMESIZE_RAW * sectors_read) / 4; i++) {
	  vorbbuf[0][i] = ((buffer[i * 4 + 1] << 8) | (0x00ff&(int)buffer[i * 4])) / 32768.f;
	  vorbbuf[1][i] = ((buffer[i * 4 + 3] << 8) | (0x00ff&(int)buffer[i * 4 + 2])) / 32768.f;
	}

	int samples_read = sectors_read * (CD_FRAMESAMPLES / 2);
	samplesdone += samples_read;
	// progress every 60 pages
	if (packetsdone >= 60) {
	  packetsdone = 0;
	  time = timer_time (timer);
	  update_statistics (total_samples_per_channel, samplesdone, time, track,
			     tracktot, 0, filenames);
	}
	vorbis_analysis_wrote (&vd, i);
      }
	  
      free (buffer);
      sector += sectors_read;
	  
      while (vorbis_analysis_blockout (&vd, &vb) == 1) {
	vorbis_analysis (&vb, &op);
	vorbis_bitrate_addblock (&vb);

	while (vorbis_bitrate_flushpacket (&vd, &op)) {
	  ogg_stream_packetin (&os, &op);
	  packetsdone++;

	  while (!eos) {
	    int result = ogg_stream_pageout (&os, &og);
	    if (result == 0) {
	      break;
	    }
	    ret = write_page (&og, out);
	    if (ret != og.header_len + og.body_len) {
	      log_msg ("Failed writing data to output stream", FL, FN, LN);
	      ret = -1;
	    } else
	      bytes_written += ret;

	    if (ogg_page_eos (&og)) {
	      eos = 1;
	    }
	  }
	}
      }
    }
  }
  ret = 0;

  update_statistics (total_samples_per_channel, samplesdone, time, track,
		     tracktot, 0, filenames);
  
  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);
  vorbis_comment_clear (&vc);
  time_elapsed = timer_time (timer);
  end_func (time_elapsed, rate, samplesdone, bytes_written);
  timer_clear (timer);
  fclose (out);
  
  return ret;
}
Esempio n. 13
0
encoder_state *encode_initialise(int channels, int rate, int managed,
        int min_br, int nom_br, int max_br, float quality, vorbis_comment *vc)
{
    encoder_state *s = calloc(1, sizeof(encoder_state));
    ogg_packet h1,h2,h3;

    /* Have vorbisenc choose a mode for us */
    vorbis_info_init(&s->vi);

    if (max_br < 0 && nom_br < 0 && min_br < 0)
       managed = 0;
    if (managed == 0 && nom_br >= 0)
        if (min_br >= 0 || max_br >= 0)
            managed = 1;
    do
    {
        if (managed)
        {
            LOG_INFO5("Encoder initialising with bitrate management: %d "
                    "channels, %d Hz, minimum bitrate %d, nominal %d, "
                    "maximum %d", channels, rate, min_br, nom_br, max_br);

            if (vorbis_encode_setup_managed (&s->vi, channels,
                        rate, max_br, nom_br, min_br))
                break;
        }
        else
        {
            if (nom_br < 0)
            {
                LOG_INFO3("Encoder initialising in VBR mode: %d channel(s), "
                        "%d Hz, quality %f", channels, rate, quality);
                if (min_br > 0 || max_br > 0)
                    LOG_INFO0("ignoring min/max bitrate, not supported in VBR "
                            "mode, use nominal-bitrate instead");
                if (vorbis_encode_setup_vbr(&s->vi, channels, rate, quality*0.1))
                    break;

#if 0
                if (max_br > 0 || min_br > 0)
                {
                    struct ovectl_ratemanage_arg ai;
                    if (vorbis_encode_ctl(&s->vi, OV_ECTL_RATEMANAGE_GET, &ai))
                        break;
                    ai.bitrate_hard_min = min_br;
                    ai.bitrate_hard_max = max_br;
                    ai.management_active = 1;
                    if (vorbis_encode_ctl(&s->vi, OV_ECTL_RATEMANAGE_SET, &ai))
                        break;
                }
#endif
            }
            else
            {
                LOG_INFO3("Encoder initialising in VBR mode: %d "
                        "channels, %d Hz, nominal %d", channels, rate, nom_br);
                if (vorbis_encode_setup_managed (&s->vi, channels,
                            rate, max_br, nom_br, max_br))
                    break;
                if (vorbis_encode_ctl (&s->vi, OV_ECTL_RATEMANAGE_SET, NULL))
                    break;
            }
        }
        if (vorbis_encode_setup_init(&s->vi))
            break;

        vorbis_analysis_init(&s->vd, &s->vi);
        vorbis_block_init(&s->vd, &s->vb);

        ogg_stream_init(&s->os, _get_serial());

        vorbis_analysis_headerout(&s->vd, vc, &h1,&h2,&h3);
        ogg_stream_packetin(&s->os, &h1);
        ogg_stream_packetin(&s->os, &h2);
        ogg_stream_packetin(&s->os, &h3);

        s->in_header = 1;
        s->samplerate = rate;
        s->samples_in_current_page = 0;
        s->prevgranulepos = 0;

        return s;
    } while (0);

    LOG_INFO0("Failed to configure encoder, verify settings");
    vorbis_info_clear(&s->vi);
    free (s);
    return NULL;
}
Esempio n. 14
0
static int encode(quicktime_t *file, 
							int16_t **input_i, 
							float **input_f, 
							int track, 
							long samples)
{
	int result = 0;
	int64_t offset = quicktime_position(file);
	quicktime_audio_map_t *track_map = &(file->atracks[track]);
	quicktime_trak_t *trak = track_map->track;
	quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
	int samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
	float **output;
	int size = 0;
	int chunk_started = 0;
	quicktime_atom_t chunk_atom;


	if(samplerate < 32000)
	{
		printf("encode: sample rate %d not supported.\n", samplerate);
		return 1;
	}





	if(!codec->encode_initialized)
	{
    	ogg_packet header;
    	ogg_packet header_comm;
    	ogg_packet header_code;


		codec->encode_initialized = 1;
		if(file->use_avi)
			trak->mdia.minf.stbl.stsd.table[0].sample_size = 0;
  		vorbis_info_init(&codec->enc_vi);

		if(codec->use_vbr)
		{
			result = vorbis_encode_setup_managed(&codec->enc_vi,
				track_map->channels, 
				samplerate, 
				codec->max_bitrate, 
				codec->nominal_bitrate, 
				codec->min_bitrate);
			result |= vorbis_encode_ctl(&codec->enc_vi, OV_ECTL_RATEMANAGE_AVG, NULL);
			result |= vorbis_encode_setup_init(&codec->enc_vi);
		}
		else
		{
			vorbis_encode_init(&codec->enc_vi,
  				track_map->channels,
				samplerate, 
				codec->max_bitrate, 
				codec->nominal_bitrate, 
				codec->min_bitrate);
		}


  		vorbis_comment_init(&codec->enc_vc);
  		vorbis_analysis_init(&codec->enc_vd, &codec->enc_vi);
  		vorbis_block_init(&codec->enc_vd, &codec->enc_vb);
    	srand(time(NULL));
		ogg_stream_init(&codec->enc_os, rand());


    	vorbis_analysis_headerout(&codec->enc_vd, 
			&codec->enc_vc,
			&header,
			&header_comm,
			&header_code);

    	ogg_stream_packetin(&codec->enc_os, &header); 
    	ogg_stream_packetin(&codec->enc_os, &header_comm);
    	ogg_stream_packetin(&codec->enc_os, &header_code);

		FLUSH_OGG1
	}
Esempio n. 15
0
/*------------------------------------------------------------------------------
 *  Open an encoding session
 *----------------------------------------------------------------------------*/
bool
VorbisLibEncoder :: open ( void )
                                                            throw ( Exception )
{
    int     ret;

    if ( isOpen() ) {
        close();
    }

    vorbis_info_init( &vorbisInfo);

    switch ( getOutBitrateMode() ) {

        case cbr:
            ret = vorbis_encode_setup_managed( &vorbisInfo,
                                               getInChannel(),
                                               getOutSampleRate(),
                                               -1,
                                               getOutBitrate() * 1000,
                                               -1)
               || vorbis_encode_ctl( &vorbisInfo, OV_ECTL_RATEMANAGE_AVG, NULL)
               || vorbis_encode_setup_init( &vorbisInfo);
            if ( ret ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;

        case abr:
            if ( (ret = vorbis_encode_init( &vorbisInfo,
                                            getInChannel(),
                                            getOutSampleRate(),
                                            -1,
                                            getOutBitrate() * 1000,
                                            -1 )) ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;

        case vbr:
            if ( (ret = vorbis_encode_init_vbr( &vorbisInfo,
                                                getInChannel(),
                                                getOutSampleRate(),
                                                getOutQuality() )) ) {
                throw Exception( __FILE__, __LINE__,
                                 "vorbis encode init error", ret);
            }
            break;
    }

    if ( (ret = vorbis_analysis_init( &vorbisDspState, &vorbisInfo)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis analysis init error", ret);
    }

    if ( (ret = vorbis_block_init( &vorbisDspState, &vorbisBlock)) ) {
        throw Exception( __FILE__, __LINE__, "vorbis block init error", ret);
    }

    if ( (ret = ogg_stream_init( &oggStreamState, 0)) ) {
        throw Exception( __FILE__, __LINE__, "ogg stream init error", ret);
    }

    // open the underlying sink
    if ( !sink->open() ) {
        throw Exception( __FILE__, __LINE__,
                         "vorbis lib opening underlying sink error");
    }

    // create an empty vorbis_comment structure
    vorbis_comment_init( &vorbisComment);

    // create the vorbis stream headers and send them to the underlying sink
    ogg_packet      header;
    ogg_packet      commentHeader;
    ogg_packet      codeHeader;

    if ( (ret = vorbis_analysis_headerout( &vorbisDspState,
                                           &vorbisComment,
                                           &header,
                                           &commentHeader,
                                           &codeHeader )) ) {
        throw Exception( __FILE__, __LINE__, "vorbis header init error", ret);
    }

    ogg_stream_packetin( &oggStreamState, &header);
    ogg_stream_packetin( &oggStreamState, &commentHeader);
    ogg_stream_packetin( &oggStreamState, &codeHeader);

    ogg_page        oggPage;
    while ( ogg_stream_flush( &oggStreamState, &oggPage) ) {
        sink->write( oggPage.header, oggPage.header_len);
        sink->write( oggPage.body, oggPage.body_len);
    }

    vorbis_comment_clear( &vorbisComment );

    // initialize the resampling coverter if needed
    if ( converter ) {
        converter->initialize( resampleRatio, getInChannel());
    }

    encoderOpen = true;

    return true;
}
Esempio n. 16
0
int encvorbisInit(hb_work_object_t *w, hb_job_t *job)
{
    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
    hb_audio_t *audio = w->audio;
    w->private_data = pv;
    pv->job = job;

    int i;
    ogg_packet header[3];

    hb_log("encvorbis: opening libvorbis");

    /* init */
    for (i = 0; i < 3; i++)
    {
        // Zero vorbis headers so that we don't crash in mk_laceXiph
        // when vorbis_encode_setup_managed fails.
        memset(w->config->vorbis.headers[i], 0, sizeof(ogg_packet));
    }
    vorbis_info_init(&pv->vi);

    pv->out_discrete_channels =
        hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

    if (audio->config.out.bitrate > 0)
    {
        if (vorbis_encode_setup_managed(&pv->vi, pv->out_discrete_channels,
                                        audio->config.out.samplerate, -1,
                                        audio->config.out.bitrate * 1000, -1))
        {
            hb_error("encvorbis: vorbis_encode_setup_managed() failed");
            *job->die = 1;
            return -1;
        }
    }
    else if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
    {
        // map VBR quality to Vorbis API (divide by 10)
        if (vorbis_encode_setup_vbr(&pv->vi, pv->out_discrete_channels,
                                    audio->config.out.samplerate,
                                    audio->config.out.quality / 10))
        {
            hb_error("encvorbis: vorbis_encode_setup_vbr() failed");
            *job->die = 1;
            return -1;
        }
    }

    if (vorbis_encode_ctl(&pv->vi, OV_ECTL_RATEMANAGE2_SET, NULL) ||
        vorbis_encode_setup_init(&pv->vi))
    {
        hb_error("encvorbis: vorbis_encode_ctl(ratemanage2_set) OR vorbis_encode_setup_init() failed");
        *job->die = 1;
        return -1;
    }

    /* add a comment */
    vorbis_comment_init(&pv->vc);
    vorbis_comment_add_tag(&pv->vc, "Encoder", "HandBrake");
    vorbis_comment_add_tag(&pv->vc, "LANGUAGE", w->config->vorbis.language);

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

    /* get the 3 headers */
    vorbis_analysis_headerout(&pv->vd, &pv->vc,
                              &header[0], &header[1], &header[2]);
    for (i = 0; i < 3; i++)
    {
        memcpy(w->config->vorbis.headers[i], &header[i], sizeof(ogg_packet));
        memcpy(w->config->vorbis.headers[i] + sizeof(ogg_packet),
               header[i].packet, header[i].bytes);
    }

    pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
    audio->config.out.samples_per_frame = OGGVORBIS_FRAME_SIZE;
    pv->buf = malloc(pv->input_samples * sizeof(float));

    pv->list = hb_list_init();

    // channel remapping
    uint64_t layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
    pv->remap_table = hb_audio_remap_build_table(layout, &hb_vorbis_chan_map,
                                                 audio->config.in.channel_map);
    if (pv->remap_table == NULL)
    {
        hb_error("encvorbisInit: hb_audio_remap_build_table() failed");
        *job->die = 1;
        return -1;
    }

    return 0;
}