Exemple #1
0
static void set_channels(struct mp_audio *mpa, int num)
{
    struct mp_chmap map;
    // "unknown" channel layouts make it easier to pass through audio data,
    // without triggering remixing.
    mp_chmap_set_unknown(&map, num);
    mp_audio_set_channels(mpa, &map);
}
Exemple #2
0
// Initialization and runtime control
static int control(struct af_instance* af, int cmd, void* arg)
{
  af_channels_t* s = af->priv;
  switch(cmd){
  case AF_CONTROL_REINIT: ;

    struct mp_chmap chmap;
    mp_chmap_set_unknown(&chmap, s->nch);
    mp_audio_set_channels(af->data, &chmap);

    // Set default channel assignment
    if(!s->router){
      int i;
      // Make sure this filter isn't redundant
      if(af->data->nch == ((struct mp_audio*)arg)->nch)
	return AF_DETACH;

      // If mono: fake stereo
      if(((struct mp_audio*)arg)->nch == 1){
	s->nr = MPMIN(af->data->nch,2);
	for(i=0;i<s->nr;i++){
	  s->route[i][FR] = 0;
	  s->route[i][TO] = i;
	}
      }
      else{
	s->nr = MPMIN(af->data->nch, ((struct mp_audio*)arg)->nch);
	for(i=0;i<s->nr;i++){
	  s->route[i][FR] = i;
	  s->route[i][TO] = i;
	}
      }
    }

    af->data->rate   = ((struct mp_audio*)arg)->rate;
    mp_audio_force_interleaved_format((struct mp_audio*)arg);
    mp_audio_set_format(af->data, ((struct mp_audio*)arg)->format);
    return check_routes(af,((struct mp_audio*)arg)->nch,af->data->nch);
  }
  return AF_UNKNOWN;
}
Exemple #3
0
static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
                           struct mp_audio *out, bool verbose)
{
    struct af_resample *s = af->priv;

    close_lavrr(af);

    s->avrctx = avresample_alloc_context();
    s->avrctx_out = avresample_alloc_context();
    if (!s->avrctx || !s->avrctx_out)
        goto error;

    enum AVSampleFormat in_samplefmt = af_to_avformat(in->format);
    enum AVSampleFormat out_samplefmt = check_output_conversion(out->format);
    enum AVSampleFormat out_samplefmtp = av_get_planar_sample_fmt(out_samplefmt);

    if (in_samplefmt == AV_SAMPLE_FMT_NONE ||
        out_samplefmt == AV_SAMPLE_FMT_NONE ||
        out_samplefmtp == AV_SAMPLE_FMT_NONE)
        goto error;

    s->out_rate    = out->rate;
    s->in_rate_af  = in->rate;
    s->in_rate     = rate_from_speed(in->rate, s->playback_speed);
    s->out_format  = out->format;
    s->in_format   = in->format;
    s->out_channels= out->channels;
    s->in_channels = in->channels;

    av_opt_set_int(s->avrctx, "filter_size",        s->opts.filter_size, 0);
    av_opt_set_int(s->avrctx, "phase_shift",        s->opts.phase_shift, 0);
    av_opt_set_int(s->avrctx, "linear_interp",      s->opts.linear, 0);

    av_opt_set_double(s->avrctx, "cutoff",          s->opts.cutoff, 0);

    int normalize = s->opts.normalize;
    if (normalize < 0)
        normalize = af->opts->audio_normalize;
#if HAVE_LIBSWRESAMPLE
    av_opt_set_double(s->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0);
#else
    av_opt_set_int(s->avrctx, "normalize_mix_level", !!normalize, 0);
#endif

    if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0)
        goto error;

    struct mp_chmap map_in = in->channels;
    struct mp_chmap map_out = out->channels;

    // Try not to do any remixing if at least one is "unknown".
    if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) {
        mp_chmap_set_unknown(&map_in, map_in.num);
        mp_chmap_set_unknown(&map_out, map_out.num);
    }

    // unchecked: don't take any channel reordering into account
    uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in);
    uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out);

    struct mp_chmap in_lavc, out_lavc;
    mp_chmap_from_lavc(&in_lavc, in_ch_layout);
    mp_chmap_from_lavc(&out_lavc, out_ch_layout);

    if (verbose && !mp_chmap_equals(&in_lavc, &out_lavc)) {
        MP_VERBOSE(af, "Remix: %s -> %s\n", mp_chmap_to_str(&in_lavc),
                                            mp_chmap_to_str(&out_lavc));
    }

    if (in_lavc.num != map_in.num) {
        // For handling NA channels, we would have to add a planarization step.
        MP_FATAL(af, "Unsupported channel remapping.\n");
        goto error;
    }

    mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc);
    transpose_order(s->reorder_in, map_in.num);

    if (mp_chmap_equals(&out_lavc, &map_out)) {
        // No intermediate step required - output new format directly.
        out_samplefmtp = out_samplefmt;
    } else {
        // Verify that we really just reorder and/or insert NA channels.
        struct mp_chmap withna = out_lavc;
        mp_chmap_fill_na(&withna, map_out.num);
        if (withna.num != map_out.num)
            goto error;
    }
    mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out);

    s->avrctx_fmt = *out;
    mp_audio_set_channels(&s->avrctx_fmt, &out_lavc);
    mp_audio_set_format(&s->avrctx_fmt, af_from_avformat(out_samplefmtp));

    s->pre_out_fmt = *out;
    mp_audio_set_format(&s->pre_out_fmt, af_from_avformat(out_samplefmt));

    // If there are NA channels, the final output will have more channels than
    // the avrctx output. Also, avrctx will output planar (out_samplefmtp was
    // not overwritten). Allocate the output frame with more channels, so the
    // NA channels can be trivially added.
    s->pool_fmt = s->avrctx_fmt;
    if (map_out.num > out_lavc.num)
        mp_audio_set_channels(&s->pool_fmt, &map_out);

    out_ch_layout = fudge_layout_conversion(af, in_ch_layout, out_ch_layout);

    // Real conversion; output is input to avrctx_out.
    av_opt_set_int(s->avrctx, "in_channel_layout",  in_ch_layout, 0);
    av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0);
    av_opt_set_int(s->avrctx, "in_sample_rate",     s->in_rate, 0);
    av_opt_set_int(s->avrctx, "out_sample_rate",    s->out_rate, 0);
    av_opt_set_int(s->avrctx, "in_sample_fmt",      in_samplefmt, 0);
    av_opt_set_int(s->avrctx, "out_sample_fmt",     out_samplefmtp, 0);

    // Just needs the correct number of channels for deplanarization.
    struct mp_chmap fake_chmap;
    mp_chmap_set_unknown(&fake_chmap, map_out.num);
    uint64_t fake_out_ch_layout = mp_chmap_to_lavc_unchecked(&fake_chmap);
    if (!fake_out_ch_layout)
        goto error;
    av_opt_set_int(s->avrctx_out, "in_channel_layout",  fake_out_ch_layout, 0);
    av_opt_set_int(s->avrctx_out, "out_channel_layout", fake_out_ch_layout, 0);

    av_opt_set_int(s->avrctx_out, "in_sample_fmt",      out_samplefmtp, 0);
    av_opt_set_int(s->avrctx_out, "out_sample_fmt",     out_samplefmt, 0);
    av_opt_set_int(s->avrctx_out, "in_sample_rate",     s->out_rate, 0);
    av_opt_set_int(s->avrctx_out, "out_sample_rate",    s->out_rate, 0);

    // API has weird requirements, quoting avresample.h:
    //  * This function can only be called when the allocated context is not open.
    //  * Also, the input channel layout must have already been set.
    avresample_set_channel_mapping(s->avrctx, s->reorder_in);

    if (avresample_open(s->avrctx) < 0 || avresample_open(s->avrctx_out) < 0) {
        MP_ERR(af, "Cannot open Libavresample Context. \n");
        goto error;
    }
    return AF_OK;

error:
    close_lavrr(af);
    return AF_ERROR;
}
Exemple #4
0
static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
                           struct mp_audio *out)
{
    struct af_resample *s = af->priv;

    enum AVSampleFormat in_samplefmt = af_to_avformat(in->format);
    enum AVSampleFormat out_samplefmt = af_to_avformat(out->format);

    if (in_samplefmt == AV_SAMPLE_FMT_NONE || out_samplefmt == AV_SAMPLE_FMT_NONE)
        return AF_ERROR;

    avresample_close(s->avrctx);
    avresample_close(s->avrctx_out);

    s->ctx.out_rate    = out->rate;
    s->ctx.in_rate     = in->rate;
    s->ctx.out_format  = out->format;
    s->ctx.in_format   = in->format;
    s->ctx.out_channels= out->channels;
    s->ctx.in_channels = in->channels;
    s->ctx.filter_size = s->opts.filter_size;
    s->ctx.phase_shift = s->opts.phase_shift;
    s->ctx.linear      = s->opts.linear;
    s->ctx.cutoff      = s->opts.cutoff;

    av_opt_set_int(s->avrctx, "filter_size",        s->ctx.filter_size, 0);
    av_opt_set_int(s->avrctx, "phase_shift",        s->ctx.phase_shift, 0);
    av_opt_set_int(s->avrctx, "linear_interp",      s->ctx.linear, 0);

    av_opt_set_double(s->avrctx, "cutoff",          s->ctx.cutoff, 0);

    if (parse_avopts(s->avrctx, s->avopts) < 0) {
        mp_msg(MSGT_VFILTER, MSGL_FATAL,
                "af_lavrresample: could not set opts: '%s'\n", s->avopts);
        return AF_ERROR;
    }

    struct mp_chmap map_in = in->channels;
    struct mp_chmap map_out = out->channels;

    // Try not to do any remixing if at least one is "unknown".
    if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) {
        mp_chmap_set_unknown(&map_in, map_in.num);
        mp_chmap_set_unknown(&map_out, map_out.num);
    }

    // unchecked: don't take any channel reordering into account
    uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in);
    uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out);

    av_opt_set_int(s->avrctx, "in_channel_layout",  in_ch_layout, 0);
    av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0);

    av_opt_set_int(s->avrctx, "in_sample_rate",     s->ctx.in_rate, 0);
    av_opt_set_int(s->avrctx, "out_sample_rate",    s->ctx.out_rate, 0);

    av_opt_set_int(s->avrctx, "in_sample_fmt",      in_samplefmt, 0);
    av_opt_set_int(s->avrctx, "out_sample_fmt",     out_samplefmt, 0);

    struct mp_chmap in_lavc;
    mp_chmap_from_lavc(&in_lavc, in_ch_layout);
    mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc);

    struct mp_chmap out_lavc;
    mp_chmap_from_lavc(&out_lavc, out_ch_layout);
    mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out);

    // Same configuration; we just reorder.
    av_opt_set_int(s->avrctx_out, "in_channel_layout",  out_ch_layout, 0);
    av_opt_set_int(s->avrctx_out, "out_channel_layout", out_ch_layout, 0);
    av_opt_set_int(s->avrctx_out, "in_sample_fmt",      out_samplefmt, 0);
    av_opt_set_int(s->avrctx_out, "out_sample_fmt",     out_samplefmt, 0);
    av_opt_set_int(s->avrctx_out, "in_sample_rate",     s->ctx.out_rate, 0);
    av_opt_set_int(s->avrctx_out, "out_sample_rate",    s->ctx.out_rate, 0);

#if USE_SET_CHANNEL_MAPPING
    // API has weird requirements, quoting avresample.h:
    //  * This function can only be called when the allocated context is not open.
    //  * Also, the input channel layout must have already been set.
    avresample_set_channel_mapping(s->avrctx, s->reorder_in);
    avresample_set_channel_mapping(s->avrctx_out, s->reorder_out);
#endif

    if (avresample_open(s->avrctx) < 0 ||
        avresample_open(s->avrctx_out) < 0)
    {
        mp_msg(MSGT_AFILTER, MSGL_ERR, "[lavrresample] Cannot open "
                "Libavresample Context. \n");
        return AF_ERROR;
    }
    return AF_OK;
}
Exemple #5
0
static int control(struct af_instance *af, int cmd, void *arg)
{
    struct af_resample *s = (struct af_resample *) af->priv;
    struct mp_audio *in   = (struct mp_audio *) arg;
    struct mp_audio *out  = (struct mp_audio *) af->data;

    switch (cmd) {
    case AF_CONTROL_REINIT: {
        struct mp_audio orig_in = *in;

        if (((out->rate    == in->rate) || (out->rate == 0)) &&
            (out->format   == in->format) &&
            (mp_chmap_equals(&out->channels, &in->channels) || out->nch == 0) &&
            s->allow_detach)
            return AF_DETACH;

        if (out->rate == 0)
            out->rate = in->rate;

        if (mp_chmap_is_empty(&out->channels))
            mp_audio_set_channels(out, &in->channels);

        enum AVSampleFormat in_samplefmt = af_to_avformat(in->format);
        if (in_samplefmt == AV_SAMPLE_FMT_NONE) {
            mp_audio_set_format(in, AF_FORMAT_FLOAT_NE);
            in_samplefmt = af_to_avformat(in->format);
        }
        enum AVSampleFormat out_samplefmt = af_to_avformat(out->format);
        if (out_samplefmt == AV_SAMPLE_FMT_NONE) {
            mp_audio_set_format(out, in->format);
            out_samplefmt = in_samplefmt;
        }

        af->mul     = (double) (out->rate * out->nch) / (in->rate * in->nch);
        af->delay   = out->nch * s->opts.filter_size / FFMIN(af->mul, 1);

        if (needs_lavrctx_reconfigure(s, in, out)) {
            avresample_close(s->avrctx);
            avresample_close(s->avrctx_out);

            s->ctx.out_rate    = out->rate;
            s->ctx.in_rate     = in->rate;
            s->ctx.out_format  = out->format;
            s->ctx.in_format   = in->format;
            s->ctx.out_channels= out->channels;
            s->ctx.in_channels = in->channels;
            s->ctx.filter_size = s->opts.filter_size;
            s->ctx.phase_shift = s->opts.phase_shift;
            s->ctx.linear      = s->opts.linear;
            s->ctx.cutoff      = s->opts.cutoff;

            ctx_opt_set_int("filter_size",        s->ctx.filter_size);
            ctx_opt_set_int("phase_shift",        s->ctx.phase_shift);
            ctx_opt_set_int("linear_interp",      s->ctx.linear);

            ctx_opt_set_dbl("cutoff",             s->ctx.cutoff);

            if (parse_avopts(s->avrctx, s->avopts) < 0) {
                mp_msg(MSGT_VFILTER, MSGL_FATAL,
                       "af_lavrresample: could not set opts: '%s'\n", s->avopts);
                return AF_ERROR;
            }

            struct mp_chmap map_in = in->channels;
            struct mp_chmap map_out = out->channels;

            // Try not to do any remixing if at least one is "unknown".
            if (mp_chmap_is_unknown(&map_in) || mp_chmap_is_unknown(&map_out)) {
                mp_chmap_set_unknown(&map_in, map_in.num);
                mp_chmap_set_unknown(&map_out, map_out.num);
            }

            // unchecked: don't take any channel reordering into account
            uint64_t in_ch_layout = mp_chmap_to_lavc_unchecked(&map_in);
            uint64_t out_ch_layout = mp_chmap_to_lavc_unchecked(&map_out);

            ctx_opt_set_int("in_channel_layout",  in_ch_layout);
            ctx_opt_set_int("out_channel_layout", out_ch_layout);

            ctx_opt_set_int("in_sample_rate",     s->ctx.in_rate);
            ctx_opt_set_int("out_sample_rate",    s->ctx.out_rate);

            ctx_opt_set_int("in_sample_fmt",      in_samplefmt);
            ctx_opt_set_int("out_sample_fmt",     out_samplefmt);

            struct mp_chmap in_lavc;
            mp_chmap_from_lavc(&in_lavc, in_ch_layout);
            mp_chmap_get_reorder(s->reorder_in, &map_in, &in_lavc);

            struct mp_chmap out_lavc;
            mp_chmap_from_lavc(&out_lavc, out_ch_layout);
            mp_chmap_get_reorder(s->reorder_out, &out_lavc, &map_out);

            // Same configuration; we just reorder.
            av_opt_set_int(s->avrctx_out, "in_channel_layout", out_ch_layout, 0);
            av_opt_set_int(s->avrctx_out, "out_channel_layout", out_ch_layout, 0);
            av_opt_set_int(s->avrctx_out, "in_sample_fmt", out_samplefmt, 0);
            av_opt_set_int(s->avrctx_out, "out_sample_fmt", out_samplefmt, 0);
            av_opt_set_int(s->avrctx_out, "in_sample_rate", s->ctx.out_rate, 0);
            av_opt_set_int(s->avrctx_out, "out_sample_rate", s->ctx.out_rate, 0);

#if USE_SET_CHANNEL_MAPPING
            // API has weird requirements, quoting avresample.h:
            //  * This function can only be called when the allocated context is not open.
            //  * Also, the input channel layout must have already been set.
            avresample_set_channel_mapping(s->avrctx, s->reorder_in);
            avresample_set_channel_mapping(s->avrctx_out, s->reorder_out);
#endif

            if (avresample_open(s->avrctx) < 0 ||
                avresample_open(s->avrctx_out) < 0)
            {
                mp_msg(MSGT_AFILTER, MSGL_ERR, "[lavrresample] Cannot open "
                       "Libavresample Context. \n");
                return AF_ERROR;
            }
        }

        return ((in->format == orig_in.format) &&
                mp_chmap_equals(&in->channels, &orig_in.channels))
               ? AF_OK : AF_FALSE;
    }
    case AF_CONTROL_FORMAT_FMT | AF_CONTROL_SET: {
        if (af_to_avformat(*(int*)arg) == AV_SAMPLE_FMT_NONE)
            return AF_FALSE;

        mp_audio_set_format(af->data, *(int*)arg);
        return AF_OK;
    }
    case AF_CONTROL_CHANNELS | AF_CONTROL_SET: {
        mp_audio_set_channels(af->data, (struct mp_chmap *)arg);
        return AF_OK;
    }
    case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET:
        out->rate = *(int *)arg;
        return AF_OK;
    }
    return AF_UNKNOWN;
}