/*
 *TODO: broken sample rate(AAC), see mplayer
 */
bool AudioResamplerFF::prepare()
{
    DPTR_D(AudioResamplerFF);
    if (!d.in_format.isValid()) {
        qWarning("src audio parameters 'channel layout(or channels), sample rate and sample format must be set before initialize resampler");
        return false;
    }
    //TODO: also in do this statistics
    qDebug("in cs: %d, cl: %lld", d.in_format.channels(), d.in_format.channelLayout());
    if (!d.in_format.channels()) {
        if (!d.in_format.channelLayout()) { //FIXME: already return
            d.in_format.setChannels(2);
            d.in_format.setChannelLayout(av_get_default_channel_layout(d.in_format.channels())); //from mplayer2
            qWarning("both channels and channel layout are not available, assume channels=%d, channel layout=%lld", d.in_format.channels(), d.in_format.channelLayout());
        } else {
            d.in_format.setChannels(av_get_channel_layout_nb_channels(d.in_format.channelLayout()));
        }
    }
    if (!d.in_format.channels())
        d.in_format.setChannels(2); //TODO: why av_get_channel_layout_nb_channels() may return 0?
    if (!d.in_format.channelLayout()) {
        qWarning("channel layout not available, use default layout");
        d.in_format.setChannelLayout(av_get_default_channel_layout(d.in_format.channels()));
    }
    qDebug("in cs: %d, cl: %lld", d.in_format.channels(), d.in_format.channelLayout());

    if (!d.out_format.channels()) {
        if (d.out_format.channelLayout())
            d.out_format.setChannels(av_get_channel_layout_nb_channels(d.out_format.channelLayout()));
        else
            d.out_format.setChannels(d.in_format.channels());
    }
    //now we have out channels
    if (!d.out_format.channelLayout())
        d.out_format.setChannelLayout(av_get_default_channel_layout(d.out_format.channels()));
    if (!d.out_format.sampleRate())
        d.out_format.setSampleRate(inAudioFormat().sampleRate());
    qDebug("out cs: %d, cl: %lld", d.out_format.channels(), d.out_format.channelLayout());
    if (d.speed <= 0)
        d.speed = 1.0;
    //DO NOT set sample rate here, we should keep the original and multiply 1/speed when needed
    //if (d.speed != 1.0)
    //    d.out_format.setSampleRate(int(qreal(d.out_format.sampleFormat())/d.speed));
    qDebug("swr speed=%.2f", d.speed);

    //d.in_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.in_sample_format) ? d.in_channels : 1;
    //d.out_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.out_sample_format) ? d.out_channels : 1;
    //swr_free(&d.context); //ffplay
    //If use swr_alloc() need to set the parameters (av_opt_set_xxx() manually or with swr_alloc_set_opts()) before calling swr_init()
    d.context = swr_alloc_set_opts(d.context
                                   , d.out_format.channelLayout()
                                   , (enum AVSampleFormat)outAudioFormat().sampleFormatFFmpeg()
                                   , qreal(outAudioFormat().sampleRate())/d.speed
                                   , d.in_format.channelLayout()
                                   , (enum AVSampleFormat)inAudioFormat().sampleFormatFFmpeg()
                                   , inAudioFormat().sampleRate()
                                   , 0 /*log_offset*/, 0 /*log_ctx*/);
    /*
    av_opt_set_int(d.context, "in_channel_layout",    d.in_channel_layout, 0);
    av_opt_set_int(d.context, "in_sample_rate",       d.in_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "in_sample_fmt", (enum AVSampleFormat)in_format.sampleFormatFFmpeg(), 0);
    av_opt_set_int(d.context, "out_channel_layout",    d.out_channel_layout, 0);
    av_opt_set_int(d.context, "out_sample_rate",       d.out_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "out_sample_fmt", (enum AVSampleFormat)out_format.sampleFormatFFmpeg(), 0);
    */
    av_log(NULL, AV_LOG_INFO, "out cl: %lld\n", d.out_format.channelLayout());
    av_log(NULL, AV_LOG_INFO, "out fmt: %d\n", d.out_format.sampleFormat());
    av_log(NULL, AV_LOG_INFO, "out freq: %d\n", d.out_format.sampleRate());
    av_log(NULL, AV_LOG_INFO, "in cl: %lld\n", d.in_format.channelLayout());
    av_log(NULL, AV_LOG_INFO, "in fmt: %d\n", d.in_format.sampleFormat());
    av_log(NULL, AV_LOG_INFO, "in freq: %d\n",  d.in_format.sampleRate());


    if (d.context) {
        int ret = swr_init(d.context);
        if (ret < 0) {
            qWarning("swr_init failed: %s", av_err2str(ret));
            return false;
        }
    } else {
        qWarning("Allocat swr context failed!");
        return false;
    }
    return true;
}
Beispiel #2
0
/*
 *TODO: broken sample rate(AAC), see mplayer
 */
bool AudioResamplerFF::prepare()
{
    DPTR_D(AudioResamplerFF);
    if (!d.in_format.isValid()) {
        qWarning("src audio parameters 'channel layout(or channels), sample rate and sample format must be set before initialize resampler");
        return false;
    }
    //TODO: also in do this statistics
    if (!d.in_format.channels()) {
        if (!d.in_format.channelLayoutFFmpeg()) { //FIXME: already return
            d.in_format.setChannels(2);
            d.in_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.in_format.channels())); //from mplayer2
            qWarning("both channels and channel layout are not available, assume channels=%d, channel layout=%lld", d.in_format.channels(), d.in_format.channelLayoutFFmpeg());
        } else {
            d.in_format.setChannels(av_get_channel_layout_nb_channels(d.in_format.channelLayoutFFmpeg()));
        }
    }
    if (!d.in_format.channels())
        d.in_format.setChannels(2); //TODO: why av_get_channel_layout_nb_channels() may return 0?
    if (!d.in_format.channelLayoutFFmpeg()) {
        qWarning("channel layout not available, use default layout");
        d.in_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.in_format.channels()));
    }
    if (!d.out_format.channels()) {
        if (d.out_format.channelLayoutFFmpeg()) {
            d.out_format.setChannels(av_get_channel_layout_nb_channels(d.out_format.channelLayoutFFmpeg()));
        } else {
            d.out_format.setChannels(d.in_format.channels());
            d.out_format.setChannelLayoutFFmpeg(d.in_format.channelLayoutFFmpeg());
        }
    }
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Unsupported) {
        d.out_format.setChannels(d.in_format.channels());
        d.out_format.setChannelLayoutFFmpeg(d.in_format.channelLayoutFFmpeg());
    }
    //now we have out channels
    if (!d.out_format.channelLayoutFFmpeg())
        d.out_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.out_format.channels()));
    if (!d.out_format.sampleRate())
        d.out_format.setSampleRate(inAudioFormat().sampleRate());
    if (d.speed <= 0)
        d.speed = 1.0;
    //DO NOT set sample rate here, we should keep the original and multiply 1/speed when needed
    //if (d.speed != 1.0)
    //    d.out_format.setSampleRate(int(qreal(d.out_format.sampleFormat())/d.speed));
    qDebug("swr speed=%.2f", d.speed);

    //d.in_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.in_sample_format) ? d.in_channels : 1;
    //d.out_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.out_sample_format) ? d.out_channels : 1;
    if (d.context)
        swr_free(&d.context); //TODO: if no free(of cause free is required), why channel mapping and layout not work if change from left to stero?
    //If use swr_alloc() need to set the parameters (av_opt_set_xxx() manually or with swr_alloc_set_opts()) before calling swr_init()
    d.context = swr_alloc_set_opts(d.context
                                   , d.out_format.channelLayoutFFmpeg()
                                   , (enum AVSampleFormat)outAudioFormat().sampleFormatFFmpeg()
                                   , qreal(outAudioFormat().sampleRate())/d.speed
                                   , d.in_format.channelLayoutFFmpeg()
                                   , (enum AVSampleFormat)inAudioFormat().sampleFormatFFmpeg()
                                   , inAudioFormat().sampleRate()
                                   , 0 /*log_offset*/, 0 /*log_ctx*/);
    /*
    av_opt_set_int(d.context, "in_channel_layout",    d.in_channel_layout, 0);
    av_opt_set_int(d.context, "in_sample_rate",       d.in_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "in_sample_fmt", (enum AVSampleFormat)in_format.sampleFormatFFmpeg(), 0);
    av_opt_set_int(d.context, "out_channel_layout",    d.out_channel_layout, 0);
    av_opt_set_int(d.context, "out_sample_rate",       d.out_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "out_sample_fmt", (enum AVSampleFormat)out_format.sampleFormatFFmpeg(), 0);
    */
    qDebug("out: {cl: %lld, fmt: %s, freq: %d}"
           , d.out_format.channelLayoutFFmpeg()
           , qPrintable(d.out_format.sampleFormatName())
           , d.out_format.sampleRate());
    qDebug("in {cl: %lld, fmt: %s, freq: %d}"
           , d.in_format.channelLayoutFFmpeg()
           , qPrintable(d.in_format.sampleFormatName())
           , d.in_format.sampleRate());

    if (!d.context) {
        qWarning("Allocat swr context failed!");
        return false;
    }
    //avresample 0.0.2(FFmpeg 0.11)~1.0.1(FFmpeg 1.1) has no channel mapping. but has remix matrix, so does swresample
//TODO: why crash if use channel mapping for L or R?
#if QTAV_HAVE(SWR_AVR_MAP) //LIBAVRESAMPLE_VERSION_INT < AV_VERSION_INT(1, 1, 0)
    bool remix = false;
    int in_c = d.in_format.channels();
    int out_c = d.out_format.channels();
    /*
     * matrix[i + stride * o] is the weight of input channel i in output channel o.
     */
    double *matrix = 0;
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Left) {
        remix = true;
        matrix = (double*)calloc(in_c*out_c, sizeof(double));
        for (int o = 0; o < out_c; ++o) {
            matrix[0 + in_c * o] = 1;
        }
    }
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Right) {
        remix = true;
        matrix = (double*)calloc(in_c*out_c, sizeof(double));
        for (int o = 0; o < out_c; ++o) {
            matrix[1 + in_c * o] = 1;
        }
    }
    if (!remix && in_c < out_c) {
        remix = true;
        //double matrix[in_c*out_c]; //C99, VLA
        matrix = (double*)calloc(in_c*out_c, sizeof(double));
        for (int i = 0, o = 0; o < out_c; ++o) {
            matrix[i + in_c * o] = 1;
            i = (i + i)%in_c;
        }
    }
    if (remix && matrix) {
        avresample_set_matrix(d.context, matrix, in_c);
        free(matrix);
    }
#else
    bool use_channel_map = false;
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Left) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = 0;
        }
    }
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Right) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = 1;
        }
    }
    if (!use_channel_map && d.in_format.channels() < d.out_format.channels()) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = i % d.in_format.channels();
        }
    }
    if (use_channel_map) {
        av_opt_set_int(d.context, "icl", d.out_format.channelLayoutFFmpeg(), 0);
        //TODO: why crash if layout is mono and set uch(i.e. always the next line)
        av_opt_set_int(d.context, "uch", d.out_format.channels(), 0);
        swr_set_channel_mapping(d.context, d.channel_map);
    }
#endif //QTAV_HAVE(SWR_AVR_MAP)
    int ret = swr_init(d.context);
    if (ret < 0) {
        qWarning("swr_init failed: %s", av_err2str(ret));
        swr_free(&d.context);
        return false;
    }
    return true;
}
Beispiel #3
0
/*
 *TODO: broken sample rate(AAC), see mplayer
 */
bool AudioResamplerFF::prepare()
{
    DPTR_D(AudioResamplerFF);
    if (!d.in_format.isValid()) {
        qWarning("src audio parameters 'channel layout(or channels), sample rate and sample format must be set before initialize resampler");
        return false;
    }
    //TODO: also in do this statistics
    if (!d.in_format.channels()) {
        if (!d.in_format.channelLayoutFFmpeg()) { //FIXME: already return
            d.in_format.setChannels(2);
            d.in_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.in_format.channels())); //from mplayer2
            qWarning("both channels and channel layout are not available, assume channels=%d, channel layout=%lld", d.in_format.channels(), d.in_format.channelLayoutFFmpeg());
        } else {
            d.in_format.setChannels(av_get_channel_layout_nb_channels(d.in_format.channelLayoutFFmpeg()));
        }
    }
    if (!d.in_format.channels())
        d.in_format.setChannels(2); //TODO: why av_get_channel_layout_nb_channels() may return 0?
    if (!d.in_format.channelLayoutFFmpeg()) {
        qWarning("channel layout not available, use default layout");
        d.in_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.in_format.channels()));
    }
    if (!d.out_format.channels()) {
        if (d.out_format.channelLayoutFFmpeg()) {
            d.out_format.setChannels(av_get_channel_layout_nb_channels(d.out_format.channelLayoutFFmpeg()));
        } else {
            d.out_format.setChannels(d.in_format.channels());
            d.out_format.setChannelLayoutFFmpeg(d.in_format.channelLayoutFFmpeg());
        }
    }
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Unsupported) {
        d.out_format.setChannels(d.in_format.channels());
        d.out_format.setChannelLayoutFFmpeg(d.in_format.channelLayoutFFmpeg());
    }
    //now we have out channels
    if (!d.out_format.channelLayoutFFmpeg())
        d.out_format.setChannelLayoutFFmpeg(av_get_default_channel_layout(d.out_format.channels()));
    if (!d.out_format.sampleRate())
        d.out_format.setSampleRate(inAudioFormat().sampleRate());
    if (d.speed <= 0)
        d.speed = 1.0;
    //DO NOT set sample rate here, we should keep the original and multiply 1/speed when needed
    //if (d.speed != 1.0)
    //    d.out_format.setSampleRate(int(qreal(d.out_format.sampleFormat())/d.speed));
    qDebug("swr speed=%.2f", d.speed);

    //d.in_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.in_sample_format) ? d.in_channels : 1;
    //d.out_planes = av_sample_fmt_is_planar((enum AVSampleFormat)d.out_sample_format) ? d.out_channels : 1;
    swr_free(&d.context); //TODO: if no free(of cause free is required), why channel mapping and layout not work if change from left to stero?
    //If use swr_alloc() need to set the parameters (av_opt_set_xxx() manually or with swr_alloc_set_opts()) before calling swr_init()
    d.context = swr_alloc_set_opts(d.context
                                   , d.out_format.channelLayoutFFmpeg()
                                   , (enum AVSampleFormat)outAudioFormat().sampleFormatFFmpeg()
                                   , qreal(outAudioFormat().sampleRate())/d.speed
                                   , d.in_format.channelLayoutFFmpeg()
                                   , (enum AVSampleFormat)inAudioFormat().sampleFormatFFmpeg()
                                   , inAudioFormat().sampleRate()
                                   , 0 /*log_offset*/, 0 /*log_ctx*/);
    /*
    av_opt_set_int(d.context, "in_channel_layout",    d.in_channel_layout, 0);
    av_opt_set_int(d.context, "in_sample_rate",       d.in_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "in_sample_fmt", (enum AVSampleFormat)in_format.sampleFormatFFmpeg(), 0);
    av_opt_set_int(d.context, "out_channel_layout",    d.out_channel_layout, 0);
    av_opt_set_int(d.context, "out_sample_rate",       d.out_format.sampleRate(), 0);
    av_opt_set_sample_fmt(d.context, "out_sample_fmt", (enum AVSampleFormat)out_format.sampleFormatFFmpeg(), 0);
    */
    qDebug("out: {cl: %lld, fmt: %s, freq: %d}"
           , d.out_format.channelLayoutFFmpeg()
           , qPrintable(d.out_format.sampleFormatName())
           , d.out_format.sampleRate());
    qDebug("in {cl: %lld, fmt: %s, freq: %d}"
           , d.in_format.channelLayoutFFmpeg()
           , qPrintable(d.in_format.sampleFormatName())
           , d.in_format.sampleRate());

    if (!d.context) {
        qWarning("Allocat swr context failed!");
        return false;
    }
    bool use_channel_map = false;
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Left) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = 0;
        }
    }
    if (d.out_format.channelLayout() == AudioFormat::ChannelLayout_Right) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = 1;
        }
    }
    if (!use_channel_map && d.in_format.channels() < d.out_format.channels()) {
        use_channel_map = true;
        memset(d.channel_map, 0, sizeof(d.channel_map));
        for (int i = 0; i < d.out_format.channels(); ++i) {
            d.channel_map[i] = i % d.in_format.channels();
        }
    }
    if (use_channel_map) {
        av_opt_set_int(d.context, "icl", d.out_format.channelLayoutFFmpeg(), 0);
        //TODO: why crash if layout is mono and set uch(i.e. always the next line)
        av_opt_set_int(d.context, "uch", d.out_format.channels(), 0);
        swr_set_channel_mapping(d.context, d.channel_map);
    }
    int ret = swr_init(d.context);
    if (ret < 0) {
        qWarning("swr_init failed: %s", av_err2str(ret));
        swr_free(&d.context);
        return false;
    }
    return true;
}