예제 #1
0
static av_cold int init(AVFilterContext *ctx)
{
    ChannelSplitContext *s = ctx->priv;
    int nb_channels;
    int ret = 0, i;

    if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) {
        av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
               s->channel_layout_str);
        ret = AVERROR(EINVAL);
        goto fail;
    }

    nb_channels = av_get_channel_layout_nb_channels(s->channel_layout);
    for (i = 0; i < nb_channels; i++) {
        uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i);
        AVFilterPad pad  = { 0 };

        pad.type = AVMEDIA_TYPE_AUDIO;
        pad.name = av_get_channel_name(channel);

        ff_insert_outpad(ctx, i, &pad);
    }

fail:
    return ret;
}
예제 #2
0
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
{
    AVFilterContext *ctx = inlink->dst;
    AVFilterLink *outlink = ctx->outputs[0];
    ShowVolumeContext *s = ctx->priv;
    int c, i, j, k;
    double values[VAR_VARS_NB];

    if (!s->out || s->out->width  != outlink->w ||
                   s->out->height != outlink->h) {
        av_frame_free(&s->out);
        s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
        if (!s->out) {
            av_frame_free(&insamples);
            return AVERROR(ENOMEM);
        }

        for (i = 0; i < outlink->h; i++)
            memset(s->out->data[0] + i * s->out->linesize[0], 0, outlink->w * 4);
    }
    s->out->pts = insamples->pts;

    for (j = 0; j < outlink->h; j++) {
        uint8_t *dst = s->out->data[0] + j * s->out->linesize[0];
        for (k = 0; k < s->w; k++) {
            dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] - s->f, 0);
            dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] - s->f, 0);
            dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] - s->f, 0);
            dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] - s->f, 0);
        }
    }

    for (c = 0; c < inlink->channels; c++) {
        float *src = (float *)insamples->extended_data[c];
        float max = 0;
        int color;

        for (i = 0; i < insamples->nb_samples; i++)
            max = FFMAX(max, src[i]);

        max = av_clipf(max, 0, 1);
        values[VAR_VOLUME] = 20.0 * log(max) / M_LN10;
        color = av_expr_eval(s->c_expr, values, NULL);

        for (j = 0; j < s->h; j++) {
            uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0];

            for (k = 0; k < s->w * max; k++)
                AV_WN32A(dst + k * 4, color);
        }

        if (s->h >= 8 && s->draw_text)
            drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2,
                     av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c)));
    }

    av_frame_free(&insamples);

    return ff_filter_frame(outlink, av_frame_clone(s->out));
}
/**
 * \fn computeChannelLayout
 * @return 
 */
bool AUDMEncoder_Lavcodec::computeChannelLayout(void)
{
#define CHANMIX(x,y) case AV_CH_##y: *o=ADM_CH_##x;cprintf(" =>%s\n",ADM_printChannel(*o));o++;break;
    
        int channels=wavheader.channels;
        CHANNEL_TYPE *o=channelMapping;
        for(int i=0;i<channels;i++)
        {
          uint64_t chan=av_channel_layout_extract_channel(CONTEXT->channel_layout,i);
          cprintf("Channel %s ",av_get_channel_name(chan))  ;
          switch(chan)
          {
              CHANMIX(FRONT_LEFT,FRONT_LEFT)
              CHANMIX(FRONT_RIGHT,FRONT_RIGHT)
              CHANMIX(LFE,LOW_FREQUENCY)
              CHANMIX(FRONT_CENTER,FRONT_CENTER)
              CHANMIX(REAR_LEFT,BACK_LEFT)
              CHANMIX(REAR_RIGHT,BACK_RIGHT)
                default:
                    ADM_warning("Channel no mapped : %s\n");
                    *o++=ADM_CH_FRONT_LEFT;
                    break;
          }
        }
        return true;
}
예제 #4
0
/* param change side data*/
static void dump_paramchange(void *ctx, AVPacketSideData *sd)
{
    int size = sd->size;
    const uint8_t *data = sd->data;
    uint32_t flags, channels, sample_rate, width, height;
    uint64_t layout;

    if (!data || sd->size < 4)
        goto fail;

    flags = AV_RL32(data);
    data += 4;
    size -= 4;

    if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) {
        if (size < 4)
            goto fail;
        channels = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "channel count %d, ", channels);
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT) {
        if (size < 8)
            goto fail;
        layout = AV_RL64(data);
        data += 8;
        size -= 8;
        av_log(ctx, AV_LOG_INFO,
               "channel layout: %s, ", av_get_channel_name(layout));
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) {
        if (size < 4)
            goto fail;
        sample_rate = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "sample_rate %d, ", sample_rate);
    }
    if (flags & AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS) {
        if (size < 8)
            goto fail;
        width = AV_RL32(data);
        data += 4;
        size -= 4;
        height = AV_RL32(data);
        data += 4;
        size -= 4;
        av_log(ctx, AV_LOG_INFO, "width %d height %d", width, height);
    }

    return;
fail:
    av_log(ctx, AV_LOG_INFO, "unknown param");
}
avtranscoder::AudioProperties audioStreamInfo( const AVFormatContext* formatContext, const size_t index )
{
	AudioProperties ap;
	AVCodecContext* codec_context = formatContext->streams[index]->codec;
	
	ap.codecId       = codec_context->codec_id;
	ap.sampleRate    = codec_context->sample_rate;
	ap.channels      = codec_context->channels;
	ap.bit_rate      = codec_context->bit_rate;
	ap.streamId      = index;

	AVCodec* codec = avcodec_find_decoder( codec_context->codec_id );
	if( codec != NULL )
	{
		ap.codecName = codec->name;
		ap.codecLongName = codec->long_name;
	}

	char buf1[1024];
	av_get_channel_layout_string( buf1, sizeof( buf1 ), -1, codec_context->channel_layout );
	
	ap.channelLayout = std::string( buf1 );

	const char* channelName = av_get_channel_name( codec_context->channel_layout );
	if( channelName )
		ap.channelName = std::string( channelName );
#ifdef FF_RESAMPLE_LIBRARY
	const char* channelDescription = av_get_channel_description( codec_context->channel_layout );
	if( channelDescription )
		ap.channelDescription = std::string( channelDescription );
#endif
	
	std::string sampleFormat = "";
	switch( codec_context->sample_fmt )
	{
		case AV_SAMPLE_FMT_NONE : ap.sampleFormat = "none"; break;
		case AV_SAMPLE_FMT_U8   : ap.sampleFormat = "unsigned 8 bits"; break;
		case AV_SAMPLE_FMT_S16  : ap.sampleFormat = "signed 16 bits"; break;
		case AV_SAMPLE_FMT_S32  : ap.sampleFormat = "signed 32 bits"; break;
		case AV_SAMPLE_FMT_FLT  : ap.sampleFormat = "float"; break;
		case AV_SAMPLE_FMT_DBL  : ap.sampleFormat = "double"; break;
		case AV_SAMPLE_FMT_U8P  : ap.sampleFormat = "unsigned 8 bits, planar"; break;
		case AV_SAMPLE_FMT_S16P : ap.sampleFormat = "signed 16 bits, planar"; break;
		case AV_SAMPLE_FMT_S32P : ap.sampleFormat = "signed 32 bits, planar"; break;
		case AV_SAMPLE_FMT_FLTP : ap.sampleFormat = "float, planar"; break;
		case AV_SAMPLE_FMT_DBLP : ap.sampleFormat = "double, planar"; break;
		case AV_SAMPLE_FMT_NB   : ap.sampleFormat = "Number of sample formats."; break;
	}

	return ap;
}
예제 #6
0
파일: rematrix.c 프로젝트: Emerica/FFmpeg
av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param,
                             double center_mix_level, double surround_mix_level,
                             double lfe_mix_level, double maxval,
                             double rematrix_volume, double *matrix_param,
                             int stride, enum AVMatrixEncoding matrix_encoding, void *log_context)
{
    int i, j, out_i;
    double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
    int64_t unaccounted, in_ch_layout, out_ch_layout;
    double maxcoef=0;
    char buf[128];

     in_ch_layout = clean_layout(log_context,  in_ch_layout_param);
    out_ch_layout = clean_layout(log_context, out_ch_layout_param);

    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
    )
        out_ch_layout = AV_CH_LAYOUT_STEREO;

    if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
       && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
    )
        in_ch_layout = AV_CH_LAYOUT_STEREO;

    if(!sane_layout(in_ch_layout)){
        av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param);
        av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
        return AVERROR(EINVAL);
    }

    if(!sane_layout(out_ch_layout)){
        av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param);
        av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
        return AVERROR(EINVAL);
    }

    for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
        if(in_ch_layout & out_ch_layout & (1ULL<<i))
            matrix[i][i]= 1.0;
    }

    unaccounted= in_ch_layout & ~out_ch_layout;

//FIXME implement dolby surround
//FIXME implement full ac3


    if(unaccounted & AV_CH_FRONT_CENTER){
        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
                matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level;
                matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level;
            } else {
                matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
                matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2;
            }
        }else
            av_assert0(0);
    }
    if(unaccounted & AV_CH_LAYOUT_STEREO){
        if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
            matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
            if(in_ch_layout & AV_CH_FRONT_CENTER)
                matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2);
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_BACK_CENTER){
        if(out_ch_layout & AV_CH_BACK_LEFT){
            matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
            matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
            matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
            matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
                matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2;
                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2;
                } else {
                    matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level;
                    matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level;
                }
            } else {
                matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2;
        }else
            av_assert0(0);
    }
    if(unaccounted & AV_CH_BACK_LEFT){
        if(out_ch_layout & AV_CH_BACK_CENTER){
            matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
            matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
            if(in_ch_layout & AV_CH_SIDE_LEFT){
                matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
                matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
            }else{
            matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
            matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
            }
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2;
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2;
                matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2;
            } else {
                matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level;
                matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2;
            matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2;
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_SIDE_LEFT){
        if(out_ch_layout & AV_CH_BACK_LEFT){
            /* if back channels do not exist in the input, just copy side
               channels to back channels, otherwise mix side into back */
            if (in_ch_layout & AV_CH_BACK_LEFT) {
                matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
                matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
            } else {
                matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
                matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
            }
        }else if(out_ch_layout & AV_CH_BACK_CENTER){
            matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
            matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2;
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2;
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2;
            } else {
                matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2;
            matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2;
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
        if(out_ch_layout & AV_CH_FRONT_LEFT){
            matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
            matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
            matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
        }else
            av_assert0(0);
    }
    /* mix LFE into front left/right or center */
    if (unaccounted & AV_CH_LOW_FREQUENCY) {
        if (out_ch_layout & AV_CH_FRONT_CENTER) {
            matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level;
        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
            matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
            matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2;
        } else
            av_assert0(0);
    }

    for(out_i=i=0; i<64; i++){
        double sum=0;
        int in_i=0;
        if((out_ch_layout & (1ULL<<i)) == 0)
            continue;
        for(j=0; j<64; j++){
            if((in_ch_layout & (1ULL<<j)) == 0)
               continue;
            if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
                matrix_param[stride*out_i + in_i] = matrix[i][j];
            else
                matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
            sum += fabs(matrix_param[stride*out_i + in_i]);
            in_i++;
        }
        maxcoef= FFMAX(maxcoef, sum);
        out_i++;
    }
    if(rematrix_volume  < 0)
        maxcoef = -rematrix_volume;

    if(maxcoef > maxval || rematrix_volume  < 0){
        maxcoef /= maxval;
        for(i=0; i<SWR_CH_MAX; i++)
            for(j=0; j<SWR_CH_MAX; j++){
                matrix_param[stride*i + j] /= maxcoef;
            }
    }

    if(rematrix_volume > 0){
        for(i=0; i<SWR_CH_MAX; i++)
            for(j=0; j<SWR_CH_MAX; j++){
                matrix_param[stride*i + j] *= rematrix_volume;
            }
    }

    av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n");
    for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
        const char *c =
            av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
        av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?");
        for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
            c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
            av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]);
        }
        av_log(log_context, AV_LOG_DEBUG, "\n");
    }
    return 0;
}
예제 #7
0
av_cold static int auto_matrix(SwrContext *s)
{
    int i, j, out_i;
    double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}};
    int64_t unaccounted, in_ch_layout, out_ch_layout;
    double maxcoef=0;
    char buf[128];
    const int matrix_encoding = s->matrix_encoding;
    float maxval;

    in_ch_layout = clean_layout(s, s->in_ch_layout);
    out_ch_layout = clean_layout(s, s->out_ch_layout);

    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
    )
        out_ch_layout = AV_CH_LAYOUT_STEREO;

    if(    in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
       && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
    )
        in_ch_layout = AV_CH_LAYOUT_STEREO;

    if(!sane_layout(in_ch_layout)){
        av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout);
        av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
        return AVERROR(EINVAL);
    }

    if(!sane_layout(out_ch_layout)){
        av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout);
        av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
        return AVERROR(EINVAL);
    }

    memset(s->matrix, 0, sizeof(s->matrix));
    for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){
        if(in_ch_layout & out_ch_layout & (1ULL<<i))
            matrix[i][i]= 1.0;
    }

    unaccounted= in_ch_layout & ~out_ch_layout;

//FIXME implement dolby surround
//FIXME implement full ac3


    if(unaccounted & AV_CH_FRONT_CENTER){
        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
                matrix[ FRONT_LEFT][FRONT_CENTER]+= s->clev;
                matrix[FRONT_RIGHT][FRONT_CENTER]+= s->clev;
            } else {
                matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
                matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2;
            }
        }else
            av_assert0(0);
    }
    if(unaccounted & AV_CH_LAYOUT_STEREO){
        if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
            matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
            if(in_ch_layout & AV_CH_FRONT_CENTER)
                matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2);
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_BACK_CENTER){
        if(out_ch_layout & AV_CH_BACK_LEFT){
            matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
            matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
            matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
            matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
                matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
                    matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev * M_SQRT1_2;
                    matrix[FRONT_RIGHT][BACK_CENTER] += s->slev * M_SQRT1_2;
                } else {
                    matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev;
                    matrix[FRONT_RIGHT][BACK_CENTER] += s->slev;
                }
            } else {
                matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2;
        }else
            av_assert0(0);
    }
    if(unaccounted & AV_CH_BACK_LEFT){
        if(out_ch_layout & AV_CH_BACK_CENTER){
            matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
            matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
            if(in_ch_layout & AV_CH_SIDE_LEFT){
                matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
                matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
            }else{
            matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
            matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
            }
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * M_SQRT1_2;
                matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * M_SQRT1_2;
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * SQRT3_2;
                matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * SQRT3_2;
            } else {
                matrix[ FRONT_LEFT][ BACK_LEFT] += s->slev;
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2;
            matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2;
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_SIDE_LEFT){
        if(out_ch_layout & AV_CH_BACK_LEFT){
            /* if back channels do not exist in the input, just copy side
               channels to back channels, otherwise mix side into back */
            if (in_ch_layout & AV_CH_BACK_LEFT) {
                matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
                matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
            } else {
                matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
                matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
            }
        }else if(out_ch_layout & AV_CH_BACK_CENTER){
            matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
            matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * M_SQRT1_2;
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * M_SQRT1_2;
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * SQRT3_2;
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * SQRT3_2;
            } else {
                matrix[ FRONT_LEFT][ SIDE_LEFT] += s->slev;
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev;
            }
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2;
            matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2;
        }else
            av_assert0(0);
    }

    if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
        if(out_ch_layout & AV_CH_FRONT_LEFT){
            matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
            matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
            matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
            matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
        }else
            av_assert0(0);
    }
    /* mix LFE into front left/right or center */
    if (unaccounted & AV_CH_LOW_FREQUENCY) {
        if (out_ch_layout & AV_CH_FRONT_CENTER) {
            matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level;
        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
            matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
            matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
        } else
            av_assert0(0);
    }

    for(out_i=i=0; i<64; i++){
        double sum=0;
        int in_i=0;
        if((out_ch_layout & (1ULL<<i)) == 0)
            continue;
        for(j=0; j<64; j++){
            if((in_ch_layout & (1ULL<<j)) == 0)
               continue;
            if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0]))
                s->matrix[out_i][in_i]= matrix[i][j];
            else
                s->matrix[out_i][in_i]= i == j && (in_ch_layout & out_ch_layout & (1ULL<<i));
            sum += fabs(s->matrix[out_i][in_i]);
            in_i++;
        }
        maxcoef= FFMAX(maxcoef, sum);
        out_i++;
    }
    if(s->rematrix_volume  < 0)
        maxcoef = -s->rematrix_volume;

    if (s->rematrix_maxval > 0) {
        maxval = s->rematrix_maxval;
    } else if (   av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
               || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
        maxval = 1.0;
    } else
        maxval = INT_MAX;

    if(maxcoef > maxval || s->rematrix_volume  < 0){
        maxcoef /= maxval;
        for(i=0; i<SWR_CH_MAX; i++)
            for(j=0; j<SWR_CH_MAX; j++){
                s->matrix[i][j] /= maxcoef;
            }
    }

    if(s->rematrix_volume > 0){
        for(i=0; i<SWR_CH_MAX; i++)
            for(j=0; j<SWR_CH_MAX; j++){
                s->matrix[i][j] *= s->rematrix_volume;
            }
    }

    av_log(s, AV_LOG_DEBUG, "Matrix coefficients:\n");
    for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){
        const char *c =
            av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i));
        av_log(s, AV_LOG_DEBUG, "%s: ", c ? c : "?");
        for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){
            c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j));
            av_log(s, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", s->matrix[i][j]);
        }
        av_log(s, AV_LOG_DEBUG, "\n");
    }
    return 0;
}
예제 #8
0
static BOOL CALLBACK dialog_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam )
{
    static char edit_buf[256] = { 0 };
    switch( message )
    {
        case WM_INITDIALOG :
            InitCommonControls();
            get_settings();
            /* threads */
            sprintf( edit_buf, "%d", reader_opt.threads );
            SetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_SPIN_THREADS ), UDM_SETBUDDY, (WPARAM)GetDlgItem( hwnd, IDC_EDIT_THREADS ), 0 );
            /* av_sync */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_AV_SYNC ), BM_SETCHECK, (WPARAM) reader_opt.av_sync ? BST_CHECKED : BST_UNCHECKED, 0 );
            /* no_create_index */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_CREATE_INDEX_FILE ), BM_SETCHECK, (WPARAM) reader_opt.no_create_index ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* force stream index */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_VIDEO ), BM_SETCHECK, (WPARAM) reader_opt.force_video ? BST_CHECKED : BST_UNCHECKED, 0 );
            sprintf( edit_buf, "%d", reader_opt.force_video_index );
            SetDlgItemText( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_AUDIO ), BM_SETCHECK, (WPARAM) reader_opt.force_audio ? BST_CHECKED : BST_UNCHECKED, 0 );
            sprintf( edit_buf, "%d", reader_opt.force_audio_index );
            SetDlgItemText( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, (LPCTSTR)edit_buf );
            /* forward_seek_threshold */
            sprintf( edit_buf, "%d", video_opt->forward_seek_threshold );
            SetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPCTSTR)edit_buf );
            SendMessage( GetDlgItem( hwnd, IDC_SPIN_FORWARD_THRESHOLD ), UDM_SETBUDDY, (WPARAM)GetDlgItem( hwnd, IDC_EDIT_FORWARD_THRESHOLD ), 0 );
            /* seek mode */
            HWND hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)seek_mode_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->seek_mode, 0 );
            /* scaler */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_SCALER );
            for( int i = 0; i < 11; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)scaler_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->scaler, 0 );
            /* apply_repeat_flag */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG ), BM_SETCHECK, (WPARAM) video_opt->apply_repeat_flag ? BST_CHECKED : BST_UNCHECKED, 0 );
            /* field_dominance */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)field_dominance_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->field_dominance, 0 );
            /* LW48 output */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LW48_OUTPUT ), BM_SETCHECK, (WPARAM) video_opt->colorspace == 0 ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* AVS bit-depth */
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH );
            for( int i = 0; i < 4; i++ )
            {
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)avs_bit_depth_list[i] );
                if( video_opt->avs.bit_depth == atoi( avs_bit_depth_list[i] ) )
                    SendMessage( hcombo, CB_SETCURSEL, i, 0 );
            }
            /* audio_delay */
            sprintf( edit_buf, "%d", audio_delay );
            SetDlgItemText( hwnd, IDC_EDIT_AUDIO_DELAY, (LPCTSTR)edit_buf );
            /* channel_layout */
            if( audio_opt->channel_layout )
            {
                char *buf = edit_buf;
                for( int i = 0; i < 64; i++ )
                {
                    uint64_t audio_channel = audio_opt->channel_layout & (1ULL << i);
                    if( audio_channel )
                    {
                        const char *channel_name = av_get_channel_name( audio_channel );
                        if( channel_name )
                        {
                            int name_length = strlen( channel_name );
                            memcpy( buf, channel_name, name_length );
                            buf += name_length;
                            *(buf++) = '+';
                        }
                    }
                }
                if( buf > edit_buf )
                    *(buf - 1) = '\0';  /* Set NULL terminator. */
                else
                    memcpy( edit_buf, "Unspecified", 12 );
            }
            else
                memcpy( edit_buf, "Unspecified", 12 );
            SetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPCTSTR)edit_buf );
            /* sample_rate */
            if( audio_opt->sample_rate > 0 )
                sprintf( edit_buf, "%d", audio_opt->sample_rate );
            else
            {
                audio_opt->sample_rate = 0;
                memcpy( edit_buf, "0 (Auto)", 12 );
            }
            SetDlgItemText( hwnd, IDC_EDIT_SAMPLE_RATE, (LPCTSTR)edit_buf );
            /* mix_level */
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER,   IDC_TEXT_MIX_LEVEL_CENTER,   0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ], edit_buf );
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, 0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], edit_buf );
            send_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE,      IDC_TEXT_MIX_LEVEL_LFE,      0, 500, audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ], edit_buf );
            /* readers */
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAVSMASH_INPUT ), BM_SETCHECK, (WPARAM) reader_disabled[0] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_AVS_INPUT        ), BM_SETCHECK, (WPARAM) reader_disabled[1] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_VPY_INPUT        ), BM_SETCHECK, (WPARAM) reader_disabled[2] ? BST_UNCHECKED : BST_CHECKED, 0 );
            SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAV_INPUT      ), BM_SETCHECK, (WPARAM) reader_disabled[3] ? BST_UNCHECKED : BST_CHECKED, 0 );
            /* dummy reader */
            sprintf( edit_buf, "%d", video_opt->dummy.width );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_WIDTH, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.height );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_HEIGHT, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.framerate_num );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, (LPCTSTR)edit_buf );
            sprintf( edit_buf, "%d", video_opt->dummy.framerate_den );
            SetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, (LPCTSTR)edit_buf );
            hcombo = GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE );
            for( int i = 0; i < 3; i++ )
                SendMessage( hcombo, CB_ADDSTRING, 0, (LPARAM)dummy_colorspace_list[i] );
            SendMessage( hcombo, CB_SETCURSEL, video_opt->dummy.colorspace, 0 );
            /* Library informations */
            if( plugin_information[0] == 0 )
                get_plugin_information();
            SetDlgItemText( hwnd, IDC_TEXT_LIBRARY_INFO, (LPCTSTR)plugin_information );
            HFONT hfont = (HFONT)GetStockObject( DEFAULT_GUI_FONT );
            LOGFONT lf = { 0 };
            GetObject( hfont, sizeof(lf), &lf );
            lf.lfWidth  *= 0.90;
            lf.lfHeight *= 0.90;
            lf.lfQuality = ANTIALIASED_QUALITY;
            SendMessage( GetDlgItem( hwnd, IDC_TEXT_LIBRARY_INFO ), WM_SETFONT, (WPARAM)CreateFontIndirect( &lf ), 1 );
            return TRUE;
        case WM_NOTIFY :
            if( wparam == IDC_SPIN_THREADS )
            {
                LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
                if( lpnmud->hdr.code == UDN_DELTAPOS )
                {
                    GetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.threads = atoi( edit_buf );
                    if( lpnmud->iDelta )
                        reader_opt.threads += lpnmud->iDelta > 0 ? -1 : 1;
                    if( reader_opt.threads < 0 )
                        reader_opt.threads = 0;
                    sprintf( edit_buf, "%d", reader_opt.threads );
                    SetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPCTSTR)edit_buf );
                }
            }
            else if( wparam == IDC_SPIN_FORWARD_THRESHOLD )
            {
                LPNMUPDOWN lpnmud = (LPNMUPDOWN)lparam;
                if( lpnmud->hdr.code == UDN_DELTAPOS )
                {
                    GetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->forward_seek_threshold = atoi( edit_buf );
                    if( lpnmud->iDelta )
                        video_opt->forward_seek_threshold += lpnmud->iDelta > 0 ? -1 : 1;
                    video_opt->forward_seek_threshold = CLIP_VALUE( video_opt->forward_seek_threshold, 1, 999 );
                    sprintf( edit_buf, "%d", video_opt->forward_seek_threshold );
                    SetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPCTSTR)edit_buf );
                }
            }
            return TRUE;
        case WM_HSCROLL :
            if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_CENTER,   IDC_TEXT_MIX_LEVEL_CENTER,   &audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ], edit_buf );
            else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_SURROUND, IDC_TEXT_MIX_LEVEL_SURROUND, &audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND], edit_buf );
            else if( GetDlgItem( hwnd, IDC_SLIDER_MIX_LEVEL_LFE ) == (HWND)lparam )
                get_mix_level( hwnd, IDC_SLIDER_MIX_LEVEL_LFE,      IDC_TEXT_MIX_LEVEL_LFE,      &audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ], edit_buf );
            return FALSE;
        case WM_COMMAND :
            switch( wparam )
            {
                case IDCANCEL :
                    EndDialog( hwnd, IDCANCEL );
                    return TRUE;
                case IDOK :
                {
                    if( !settings_path )
                        settings_path = (char *)settings_path_list[0];
                    FILE *ini = fopen( settings_path, "w" );
                    if( !ini )
                    {
                        MESSAGE_BOX_DESKTOP( MB_ICONERROR | MB_OK, "Failed to update configuration file" );
                        return FALSE;
                    }
                    /* threads */
                    GetDlgItemText( hwnd, IDC_EDIT_THREADS, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.threads = MAX( atoi( edit_buf ), 0 );
                    if( reader_opt.threads > 0 )
                        fprintf( ini, "threads=%d\n", reader_opt.threads );
                    else
                        fprintf( ini, "threads=0 (auto)\n" );
                    /* av_sync */
                    reader_opt.av_sync = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_AV_SYNC ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "av_sync=%d\n", reader_opt.av_sync );
                    /* no_create_index */
                    reader_opt.no_create_index = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_CREATE_INDEX_FILE ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "no_create_index=%d\n", reader_opt.no_create_index );
                    /* force stream index */
                    reader_opt.force_video = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_VIDEO ), BM_GETCHECK, 0, 0 ));
                    GetDlgItemText( hwnd, IDC_EDIT_FORCE_VIDEO_INDEX, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.force_video_index = MAX( atoi( edit_buf ), -1 );
                    fprintf( ini, "force_video_index=%d:%d\n", reader_opt.force_video, reader_opt.force_video_index );
                    reader_opt.force_audio = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_FORCE_AUDIO ), BM_GETCHECK, 0, 0 ));
                    GetDlgItemText( hwnd, IDC_EDIT_FORCE_AUDIO_INDEX, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    reader_opt.force_audio_index = MAX( atoi( edit_buf ), -1 );
                    fprintf( ini, "force_audio_index=%d:%d\n", reader_opt.force_audio, reader_opt.force_audio_index );
                    /* seek_mode */
                    video_opt->seek_mode = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SEEK_MODE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "seek_mode=%d\n", video_opt->seek_mode );
                    /* forward_seek_threshold */
                    GetDlgItemText( hwnd, IDC_EDIT_FORWARD_THRESHOLD, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->forward_seek_threshold = CLIP_VALUE( atoi( edit_buf ), 1, 999 );
                    fprintf( ini, "forward_threshold=%d\n", video_opt->forward_seek_threshold );
                    /* scaler */
                    video_opt->scaler = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_SCALER ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "scaler=%d\n", video_opt->scaler );
                    /* apply_repeat_flag */
                    video_opt->apply_repeat_flag = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_APPLY_REPEAT_FLAG ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "apply_repeat_flag=%d\n", video_opt->apply_repeat_flag );
                    /* field_dominance */
                    video_opt->field_dominance = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_FIELD_DOMINANCE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "field_dominance=%d\n", video_opt->field_dominance );
                    /* LW48 output */
                    video_opt->colorspace = (BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LW48_OUTPUT ), BM_GETCHECK, 0, 0 )) ? OUTPUT_LW48 : 0;
                    fprintf( ini, "colorspace=%d\n", video_opt->colorspace );
                    /* AVS bit-depth */
                    video_opt->avs.bit_depth = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_AVS_BITDEPTH ), CB_GETCURSEL, 0, 0 );
                    video_opt->avs.bit_depth = atoi( avs_bit_depth_list[ video_opt->avs.bit_depth ] );
                    fprintf( ini, "avs_bit_depth=%d\n", video_opt->avs.bit_depth );
                    /* audio_delay */
                    GetDlgItemText( hwnd, IDC_EDIT_AUDIO_DELAY, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_delay = atoi( edit_buf );
                    fprintf( ini, "audio_delay=%d\n", audio_delay );
                    /* channel_layout */
                    GetDlgItemText( hwnd, IDC_EDIT_CHANNEL_LAYOUT, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_opt->channel_layout = av_get_channel_layout( edit_buf );
                    fprintf( ini, "channel_layout=0x%"PRIx64"\n", audio_opt->channel_layout );
                    /* sample_rate */
                    GetDlgItemText( hwnd, IDC_EDIT_SAMPLE_RATE, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    audio_opt->sample_rate = atoi( edit_buf );
                    fprintf( ini, "sample_rate=%d\n", audio_opt->sample_rate );
                    /* mix_level */
                    fprintf( ini, "mix_level=%d:%d:%d\n",
                             audio_opt->mix_level[MIX_LEVEL_INDEX_CENTER  ],
                             audio_opt->mix_level[MIX_LEVEL_INDEX_SURROUND],
                             audio_opt->mix_level[MIX_LEVEL_INDEX_LFE     ] );
                    /* readers */
                    reader_disabled[0] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAVSMASH_INPUT ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[1] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_AVS_INPUT        ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[2] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_VPY_INPUT        ), BM_GETCHECK, 0, 0 ));
                    reader_disabled[3] = !(BST_CHECKED == SendMessage( GetDlgItem( hwnd, IDC_CHECK_LIBAV_INPUT      ), BM_GETCHECK, 0, 0 ));
                    fprintf( ini, "libavsmash_disabled=%d\n", reader_disabled[0] );
                    fprintf( ini, "avs_disabled=%d\n",        reader_disabled[1] );
                    fprintf( ini, "vpy_disabled=%d\n",        reader_disabled[2] );
                    fprintf( ini, "libav_disabled=%d\n",      reader_disabled[3] );
                    /* dummy reader */
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_WIDTH, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.width = MAX( atoi( edit_buf ), 32 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_HEIGHT, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.height = MAX( atoi( edit_buf ), 32 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_NUM, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.framerate_num = MAX( atoi( edit_buf ), 1 );
                    GetDlgItemText( hwnd, IDC_EDIT_DUMMY_FRAMERATE_DEN, (LPTSTR)edit_buf, sizeof(edit_buf) );
                    video_opt->dummy.framerate_den = MAX( atoi( edit_buf ), 1 );
                    video_opt->dummy.colorspace = SendMessage( GetDlgItem( hwnd, IDC_COMBOBOX_DUMMY_COLORSPACE ), CB_GETCURSEL, 0, 0 );
                    fprintf( ini, "dummy_resolution=%dx%d\n", video_opt->dummy.width, video_opt->dummy.height );
                    fprintf( ini, "dummy_framerate=%d/%d\n", video_opt->dummy.framerate_num, video_opt->dummy.framerate_den );
                    fprintf( ini, "dummy_colorspace=%d\n", video_opt->dummy.colorspace );
                    fclose( ini );
                    EndDialog( hwnd, IDOK );
                    MESSAGE_BOX_DESKTOP( MB_OK, "Please reopen the input file for updating settings!" );
                    return TRUE;
                }
                default :
                    return FALSE;
            }
        case WM_CLOSE :
            EndDialog( hwnd, IDOK );
            return TRUE;
        default :
            return FALSE;
    }
}