Exemple #1
0
hb_audio_remap_t* hb_audio_remap_init(uint64_t channel_layout,
                                      hb_chan_map_t *map_out,
                                      hb_chan_map_t *map_in)
{
    hb_audio_remap_t *remap = malloc(sizeof(hb_audio_remap_t));
    if (remap == NULL)
        return NULL;

    remap->remap_table = hb_audio_remap_build_table(channel_layout,
                                                    map_out, map_in);
    if (remap->remap_table == NULL)
    {
        hb_audio_remap_free(remap);
        return NULL;
    }

    int ii;
    remap->nchannels    = av_get_channel_layout_nb_channels(channel_layout);
    remap->sample_size  = remap->nchannels * sizeof(hb_sample_t);
    remap->remap_needed = 0;
    for (ii = 0; ii < remap->nchannels; ii++)
    {
        if (remap->remap_table[ii] != ii)
        {
            remap->remap_needed = 1;
            break;
        }
    }

    return remap;
}
Exemple #2
0
void hb_audio_remap_set_channel_layout(hb_audio_remap_t *remap,
                                       uint64_t channel_layout,
                                       int channels)
{
    if (remap != NULL)
    {
        int ii;
        remap->remap_needed = 0;

        // in some cases, remapping is not necessary and/or supported
        if (channels > HB_AUDIO_REMAP_MAX_CHANNELS)
        {
            hb_log("hb_audio_remap_set_channel_layout: too many channels (%d)",
                   channels);
            return;
        }
        if (remap->channel_map_in == remap->channel_map_out)
        {
            return;
        }

        // sanitize the layout
        channel_layout = hb_ff_layout_xlat(channel_layout, channels);
        if (channel_layout == AV_CH_LAYOUT_STEREO_DOWNMIX)
        {
            channel_layout = AV_CH_LAYOUT_STEREO;
        }
        remap->nchannels = av_get_channel_layout_nb_channels(channel_layout);

        // build the table and check whether remapping is necessary
        hb_audio_remap_build_table(remap->channel_map_out,
                                   remap->channel_map_in, channel_layout,
                                   remap->table);
        for (ii = 0; ii < remap->nchannels; ii++)
        {
            if (remap->table[ii] != ii)
            {
                remap->remap_needed = 1;
                break;
            }
        }
    }
}
Exemple #3
0
/***********************************************************************
 * hb_work_encfaac_init
 ***********************************************************************
 *
 **********************************************************************/
int encfaacInit( 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;
    faacEncConfigurationPtr cfg;
    uint8_t * bytes;
    unsigned long length;

    w->private_data = pv;

    pv->job   = job;

	/* pass the number of channels used into the private work data */
    pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

    pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels,
                            &pv->input_samples, &pv->output_bytes );
    pv->buf  = malloc( pv->input_samples * sizeof( float ) );
    pv->obuf = malloc( pv->output_bytes );
    pv->framedur = 90000.0 * pv->input_samples /
                   ( audio->config.out.samplerate * pv->out_discrete_channels );
    audio->config.out.samples_per_frame = pv->input_samples / pv->out_discrete_channels;

    cfg                = faacEncGetCurrentConfiguration( pv->faac );
    cfg->mpegVersion   = MPEG4;
    cfg->aacObjectType = LOW;
    cfg->allowMidside  = 1;

    /* channel configuration & remapping */
    uint64_t layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
    hb_audio_remap_build_table(&hb_aac_chan_map, audio->config.in.channel_map,
                               layout, cfg->channel_map);

    switch (audio->config.out.mixdown)
    {
        case HB_AMIXDOWN_7POINT1:
            cfg->channelConfiguration = 0;
            cfg->numFrontChannels     = 3;
            cfg->numSideChannels      = 2;
            cfg->numBackChannels      = 2;
            cfg->numLFEChannels       = 1;
            break;

        case HB_AMIXDOWN_6POINT1:
            cfg->channelConfiguration = 0;
            cfg->numFrontChannels     = 3;
            cfg->numSideChannels      = 0;
            cfg->numBackChannels      = 3;
            cfg->numLFEChannels       = 1;
            break;

        case HB_AMIXDOWN_5_2_LFE:
            cfg->channelConfiguration = 7;
            break;

        default:
            cfg->channelConfiguration =
                hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);
            break;
    }

    cfg->useTns        = 0;
    cfg->bitRate       = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */
    cfg->bandWidth     = 0;
    cfg->outputFormat  = 0;
    cfg->inputFormat   =  FAAC_INPUT_FLOAT;

    if( !faacEncSetConfiguration( pv->faac, cfg ) )
    {
        hb_log( "faacEncSetConfiguration failed" );
        *job->done_error = HB_ERROR_INIT;
        *job->die = 1;
        return 0;
    }

    if( faacEncGetDecoderSpecificInfo( pv->faac, &bytes, &length ) < 0 )
    {
        hb_log( "faacEncGetDecoderSpecificInfo failed" );
        *job->done_error = HB_ERROR_INIT;
        *job->die = 1;
        return 0;
    }
    memcpy( w->config->extradata.bytes, bytes, length );
    w->config->extradata.length = length;
    free( bytes );

    pv->list = hb_list_init();

    return 0;
}
Exemple #4
0
/***********************************************************************
 * hb_work_encfaac_init
 ***********************************************************************
 *
 **********************************************************************/
int encfaacInit( 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;
    faacEncConfigurationPtr cfg;
    uint8_t * bytes;
    unsigned long length;

    w->private_data = pv;

    pv->job   = job;

	/* pass the number of channels used into the private work data */
    pv->out_discrete_channels = hb_mixdown_get_discrete_channel_count(audio->config.out.mixdown);

    /* if the sample rate is 'auto' and that has given us an invalid output */
    /* rate, map it to the next highest output rate or 48K if above the highest. */
    int rate_index = find_samplerate(audio->config.out.samplerate);
    if ( audio->config.out.samplerate != valid_rates[rate_index] )
    {
        int rate = valid_rates[valid_rates[rate_index]? rate_index : rate_index - 1];
        hb_log( "encfaac changing output samplerate from %d to %d",
                audio->config.out.samplerate, rate );
        audio->config.out.samplerate = rate;

        /* if the new rate is over the max bandwidth per channel limit */
        /* lower the bandwidth. */
        double bw = audio->config.out.bitrate * 1000 / pv->out_discrete_channels;
        if ( bw > (double)rate * (6144./1024.) )
        {
            int newbr = (double)rate * (6.144/1024.) * pv->out_discrete_channels;
            hb_log( "encfaac changing output bitrate from %d to %d",
                    audio->config.out.bitrate, newbr );
            audio->config.out.bitrate = newbr;
        }
    }

    pv->faac = faacEncOpen( audio->config.out.samplerate, pv->out_discrete_channels,
                            &pv->input_samples, &pv->output_bytes );
    pv->buf  = malloc( pv->input_samples * sizeof( float ) );
    pv->obuf = malloc( pv->output_bytes );
    pv->framedur = 90000.0 * pv->input_samples /
                   ( audio->config.out.samplerate * pv->out_discrete_channels );
    audio->config.out.samples_per_frame = pv->input_samples / pv->out_discrete_channels;

    cfg                = faacEncGetCurrentConfiguration( pv->faac );
    cfg->mpegVersion   = MPEG4;
    cfg->aacObjectType = LOW;
    cfg->allowMidside  = 1;

    // channel remapping, LFE
    uint64_t layout;
    int *remap_table;
    layout = hb_ff_mixdown_xlat(audio->config.out.mixdown, NULL);
    remap_table = hb_audio_remap_build_table(layout, &hb_aac_chan_map,
                                             audio->config.in.channel_map);
    if (remap_table != NULL)
    {
        // faac does its own remapping
        memcpy(cfg->channel_map, remap_table,
               pv->out_discrete_channels * sizeof(int));
        free(remap_table);
    }
    cfg->useLfe = !!(layout & AV_CH_LOW_FREQUENCY);

    cfg->useTns        = 0;
    cfg->bitRate       = audio->config.out.bitrate * 1000 / pv->out_discrete_channels; /* Per channel */
    cfg->bandWidth     = 0;
    cfg->outputFormat  = 0;
    cfg->inputFormat   =  FAAC_INPUT_FLOAT;

    if( !faacEncSetConfiguration( pv->faac, cfg ) )
    {
        hb_log( "faacEncSetConfiguration failed" );
        *job->die = 1;
        return 0;
    }

    if( faacEncGetDecoderSpecificInfo( pv->faac, &bytes, &length ) < 0 )
    {
        hb_log( "faacEncGetDecoderSpecificInfo failed" );
        *job->die = 1;
        return 0;
    }
    memcpy( w->config->extradata.bytes, bytes, length );
    w->config->extradata.length = length;
    free( bytes );

    pv->list = hb_list_init();

    return 0;
}
Exemple #5
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;
}