diff options
Diffstat (limited to 'audio/filter')
-rw-r--r-- | audio/filter/af.c | 260 | ||||
-rw-r--r-- | audio/filter/af.h | 5 | ||||
-rw-r--r-- | audio/filter/af_delay.c | 194 | ||||
-rw-r--r-- | audio/filter/af_format.c | 16 | ||||
-rw-r--r-- | audio/filter/af_lavcac3enc.c | 46 | ||||
-rw-r--r-- | audio/filter/af_lavrresample.c | 21 | ||||
-rw-r--r-- | audio/filter/af_volume.c | 20 |
7 files changed, 181 insertions, 381 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c index 21b0982692..a132965295 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -31,7 +31,6 @@ #include "af.h" // Static list of filters -extern const struct af_info af_info_delay; extern const struct af_info af_info_channels; extern const struct af_info af_info_format; extern const struct af_info af_info_volume; @@ -46,7 +45,6 @@ extern const struct af_info af_info_lavfi; extern const struct af_info af_info_rubberband; static const struct af_info *const filter_list[] = { - &af_info_delay, &af_info_channels, &af_info_format, &af_info_volume, @@ -256,6 +254,8 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at, mp_snprintf_cat(b, sizeof(b), "\"%s\" ", af->label); if (af->data) mp_snprintf_cat(b, sizeof(b), "%s", mp_audio_config_to_str(af->data)); + if (af->auto_inserted) + mp_snprintf_cat(b, sizeof(b), " [a]"); if (af == at) mp_snprintf_cat(b, sizeof(b), " <-"); MP_MSG(s, msg_level, "%s\n", b); @@ -266,164 +266,156 @@ static void af_print_filter_chain(struct af_stream *s, struct af_instance *at, MP_MSG(s, msg_level, " [ao] %s\n", mp_audio_config_to_str(&s->output)); } -// in is what af can take as input - insert a conversion filter if the actual -// input format doesn't match what af expects. -// Returns: -// AF_OK: must call af_reinit() or equivalent, format matches (or is closer) -// AF_FALSE: nothing was changed, format matches -// else: error -static int af_fix_format_conversion(struct af_stream *s, - struct af_instance **p_af, - struct mp_audio in) +static void reset_formats(struct af_stream *s) { - int rv; - struct af_instance *af = *p_af; - struct af_instance *prev = af->prev; - struct mp_audio actual = *prev->data; - if (actual.format == in.format) - return AF_FALSE; - int dstfmt = in.format; - char *filter = "lavrresample"; - if (!af_lavrresample_test_conversion(actual.format, dstfmt)) - return AF_ERROR; - if (strcmp(filter, prev->info->name) == 0) { - if (prev->control(prev, AF_CONTROL_SET_FORMAT, &dstfmt) == AF_OK) { - *p_af = prev; - return AF_OK; - } - return AF_ERROR; - } - struct af_instance *new = af_prepend(s, af, filter, NULL); - if (new == NULL) - return AF_ERROR; - new->auto_inserted = true; - if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_FORMAT, &dstfmt))) { - af_remove(s, new); - return rv; + struct mp_audio none = {0}; + for (struct af_instance *af = s->first; af; af = af->next) { + if (af != s->first && af != s->last) + mp_audio_copy_config(af->data, &none); } - *p_af = new; - return AF_OK; } -// same as af_fix_format_conversion - only wrt. channels -static int af_fix_channels(struct af_stream *s, struct af_instance **p_af, - struct mp_audio in) +static int filter_reinit(struct af_instance *af) { - int rv; - struct af_instance *af = *p_af; struct af_instance *prev = af->prev; - struct mp_audio actual = *prev->data; - if (mp_chmap_equals(&actual.channels, &in.channels)) - return AF_FALSE; - if (prev->control(prev, AF_CONTROL_SET_CHANNELS, &in.channels) == AF_OK) { - *p_af = prev; - return AF_OK; - } - char *filter = "lavrresample"; - struct af_instance *new = af_prepend(s, af, filter, NULL); - if (new == NULL) + assert(prev); + + // Check if this is the first filter + struct mp_audio in = *prev->data; + // Reset just in case... + mp_audio_set_null_data(&in); + + if (!mp_audio_config_valid(&in)) return AF_ERROR; - new->auto_inserted = true; - if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_CHANNELS, &in.channels))) - return rv; - *p_af = new; - return AF_OK; + + af->fmt_in = in; + int rv = af->control(af, AF_CONTROL_REINIT, &in); + if (rv == AF_OK && !mp_audio_config_equals(&in, prev->data)) + rv = AF_FALSE; // conversion filter needed + if (rv == AF_FALSE) + af->fmt_in = in; + + if (rv == AF_OK) { + if (!mp_audio_config_valid(af->data)) + return AF_ERROR; + af->fmt_out = *af->data; + } + + return rv; } -static int af_fix_rate(struct af_stream *s, struct af_instance **p_af, - struct mp_audio in) +static int filter_reinit_with_conversion(struct af_stream *s, struct af_instance *af) { - int rv; - struct af_instance *af = *p_af; - struct af_instance *prev = af->prev; - struct mp_audio actual = *prev->data; - if (actual.rate == in.rate) - return AF_FALSE; - if (prev->control(prev, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate) == AF_OK) { - *p_af = prev; - return AF_OK; + int rv = filter_reinit(af); + + // Conversion filter is needed + if (rv == AF_FALSE) { + // First try if we can change the output format of the previous + // filter to the input format the current filter is expecting. + struct mp_audio in = af->fmt_in; + if (af->prev != s->first && !mp_audio_config_equals(af->prev->data, &in)) { + // This should have been successful (because it succeeded + // before), even if just reverting to the old output format. + mp_audio_copy_config(af->prev->data, &in); + rv = filter_reinit(af->prev); + if (rv != AF_OK) + return rv; + } + if (!mp_audio_config_equals(af->prev->data, &in)) { + // Retry with conversion filter added. + struct af_instance *new = + af_prepend(s, af, "lavrresample", NULL); + if (!new) + return AF_ERROR; + new->auto_inserted = true; + mp_audio_copy_config(new->data, &in); + rv = filter_reinit(new); + if (rv != AF_OK) + af_remove(s, new); + } + if (rv == AF_OK) + rv = filter_reinit(af); } - char *filter = "lavrresample"; - struct af_instance *new = af_prepend(s, af, filter, NULL); - if (new == NULL) - return AF_ERROR; - new->auto_inserted = true; - if (AF_OK != (rv = new->control(new, AF_CONTROL_SET_RESAMPLE_RATE, &in.rate))) - return rv; - *p_af = new; - return AF_OK; + + return rv; } -static void reset_formats(struct af_stream *s) +static int af_find_output_conversion(struct af_stream *s, struct mp_audio *cfg) { - for (struct af_instance *af = s->first; af; af = af->next) { - af->control(af, AF_CONTROL_SET_RESAMPLE_RATE, &(int){0}); - af->control(af, AF_CONTROL_SET_CHANNELS, &(struct mp_chmap){0}); - af->control(af, AF_CONTROL_SET_FORMAT, &(int){0}); + assert(mp_audio_config_valid(&s->output)); + assert(s->initialized > 0); + + if (mp_chmap_equals_reordered(&s->input.channels, &s->output.channels)) + return AF_ERROR; + + // Heuristic to detect point of conversion. If it looks like something + // more complicated is going on, better bail out. + // We expect that the last filter converts channels. + struct af_instance *conv = s->last->prev; + if (!conv->auto_inserted) + return AF_ERROR; + if (!(mp_chmap_equals_reordered(&conv->fmt_in.channels, &s->input.channels) && + mp_chmap_equals_reordered(&conv->fmt_out.channels, &s->output.channels))) + return AF_ERROR; + // Also, should be the only one which does auto conversion. + for (struct af_instance *af = s->first->next; af != s->last; af = af->next) + { + if (af != conv && af->auto_inserted && + !mp_chmap_equals_reordered(&af->fmt_in.channels, &af->fmt_out.channels)) + return AF_ERROR; } + // And not if it's the only filter. + if (conv->prev == s->first && conv->next == s->last) + return AF_ERROR; + + *cfg = s->output; + return AF_OK; } // Return AF_OK on success or AF_ERROR on failure. -// Warning: -// A failed af_reinit() leaves the audio chain behind in a useless, broken -// state (for example, format filters that were tentatively inserted stay -// inserted). -// In that case, you should always rebuild the filter chain, or abort. -static int af_reinit(struct af_stream *s) -{ +static int af_do_reinit(struct af_stream *s, bool second_pass) +{ + struct mp_audio convert_early = {0}; + if (second_pass) { + // If a channel conversion happens, and it is done by an auto-inserted + // filter, then insert a filter to convert it early. Otherwise, do + // nothing and return immediately. + if (af_find_output_conversion(s, &convert_early) != AF_OK) + return AF_OK; + } + remove_auto_inserted_filters(s); af_chain_forget_frames(s); reset_formats(s); s->first->fmt_in = s->first->fmt_out = s->input; + + if (mp_audio_config_valid(&convert_early)) { + struct af_instance *new = af_prepend(s, s->first, "lavrresample", NULL); + if (!new) + return AF_ERROR; + new->auto_inserted = true; + mp_audio_copy_config(new->data, &convert_early); + int rv = filter_reinit(new); + if (rv != AF_DETACH && rv != AF_OK) + return AF_ERROR; + MP_VERBOSE(s, "Moving up output conversion.\n"); + } + // Start with the second filter, as the first filter is the special input // filter which needs no initialization. struct af_instance *af = s->first->next; - // Up to 4 retries per filter (channel, rate, format conversions) - int max_retry = 4; - int retry = 0; while (af) { - if (retry >= max_retry) - goto negotiate_error; - - // Check if this is the first filter - struct mp_audio in = *af->prev->data; - // Reset just in case... - mp_audio_set_null_data(&in); - - if (!mp_audio_config_valid(&in)) - goto error; + int rv = filter_reinit_with_conversion(s, af); - af->fmt_in = in; - int rv = af->control(af, AF_CONTROL_REINIT, &in); - if (rv == AF_OK && !mp_audio_config_equals(&in, af->prev->data)) - rv = AF_FALSE; // conversion filter needed switch (rv) { case AF_OK: - if (!mp_audio_config_valid(af->data)) - goto error; - af->fmt_out = *af->data; af = af->next; break; - case AF_FALSE: { // Configuration filter is needed - if (af_fix_channels(s, &af, in) == AF_OK) { - retry++; - continue; - } - if (af_fix_rate(s, &af, in) == AF_OK) { - retry++; - continue; - } - // Do this last, to prevent "format->lavrresample" being added to - // the filter chain when output formats not supported by - // af_lavrresample are in use. - if (af_fix_format_conversion(s, &af, in) == AF_OK) { - retry++; - continue; - } + case AF_FALSE: { // If the format conversion is (probably) caused by spdif, then // (as a feature) drop the filter, instead of failing hard. int fmt_in1 = af->prev->data->format; - int fmt_in2 = in.format; + int fmt_in2 = af->fmt_in.format; if (af_fmt_is_valid(fmt_in1) && af_fmt_is_valid(fmt_in2)) { bool spd1 = af_fmt_is_spdif(fmt_in1); bool spd2 = af_fmt_is_spdif(fmt_in2); @@ -434,7 +426,6 @@ static int af_reinit(struct af_stream *s) struct af_instance *aft = af->prev; af_remove(s, af); af = aft->next; - retry++; continue; } } @@ -452,8 +443,6 @@ static int af_reinit(struct af_stream *s) af->info->name, rv); goto error; } - if (af && !af->auto_inserted) - retry = 0; } /* Set previously unset fields in s->output to those of the filter chain @@ -477,6 +466,19 @@ error: return AF_ERROR; } +static int af_reinit(struct af_stream *s) +{ + int r = af_do_reinit(s, false); + if (r == AF_OK && mp_audio_config_valid(&s->output)) { + r = af_do_reinit(s, true); + if (r != AF_OK) { + MP_ERR(s, "Failed second pass filter negotiation.\n"); + r = af_do_reinit(s, false); + } + } + return r; +} + // Uninit and remove all filters void af_uninit(struct af_stream *s) { diff --git a/audio/filter/af.h b/audio/filter/af.h index 9c49081f66..697024b781 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -112,9 +112,6 @@ struct af_stream { enum af_control { AF_CONTROL_REINIT = 1, AF_CONTROL_RESET, - AF_CONTROL_SET_RESAMPLE_RATE, - AF_CONTROL_SET_FORMAT, - AF_CONTROL_SET_CHANNELS, AF_CONTROL_SET_VOLUME, AF_CONTROL_GET_VOLUME, AF_CONTROL_SET_PAN_LEVEL, @@ -160,6 +157,4 @@ int af_test_output(struct af_instance *af, struct mp_audio *out); int af_from_ms(int n, float *in, int *out, int rate, float mi, float ma); float af_softclip(float a); -bool af_lavrresample_test_conversion(int src_format, int dst_format); - #endif /* MPLAYER_AF_H */ diff --git a/audio/filter/af_delay.c b/audio/filter/af_delay.c deleted file mode 100644 index 8d1cca8a72..0000000000 --- a/audio/filter/af_delay.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This audio filter delays the output signal for the different - * channels and can be used for simple position panning. - * An extension for this filter would be a reverb. - * - * Original author: Anders - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * mpv is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> - -#include "common/common.h" -#include "af.h" - -#define L 65536 - -#define UPDATEQI(qi) qi=(qi+1)&(L-1) - -// Data for specific instances of this filter -typedef struct af_delay_s -{ - void* q[AF_NCH]; // Circular queues used for delaying audio signal - int wi[AF_NCH]; // Write index - int ri; // Read index - float d[AF_NCH]; // Delay [ms] - char *delaystr; -}af_delay_t; - -// Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) -{ - af_delay_t* s = af->priv; - switch(cmd){ - case AF_CONTROL_REINIT:{ - int i; - struct mp_audio *in = arg; - - if (in->bps != 1 && in->bps != 2 && in->bps != 4) { - MP_FATAL(af, "Sample format not supported\n"); - return AF_ERROR; - } - - // Free prevous delay queues - for(i=0;i<af->data->nch;i++) - free(s->q[i]); - - mp_audio_force_interleaved_format(in); - mp_audio_copy_config(af->data, in); - - // Allocate new delay queues - for(i=0;i<af->data->nch;i++){ - s->q[i] = calloc(L,af->data->bps); - if(NULL == s->q[i]) - MP_FATAL(af, "Out of memory\n"); - } - - if(AF_OK != af_from_ms(AF_NCH, s->d, s->wi, af->data->rate, 0.0, 1000.0)) - return AF_ERROR; - s->ri = 0; - for(i=0;i<AF_NCH;i++){ - MP_DBG(af, "Channel %i delayed by %0.3fms\n", - i,MPCLAMP(s->d[i],0.0,1000.0)); - MP_TRACE(af, "Channel %i delayed by %i samples\n", - i,s->wi[i]); - } - return AF_OK; - } - } - return AF_UNKNOWN; -} - -// Deallocate memory -static void uninit(struct af_instance* af) -{ - int i; - - for(i=0;i<AF_NCH;i++) - free(((af_delay_t*)(af->priv))->q[i]); -} - -static int filter_frame(struct af_instance *af, struct mp_audio *c) -{ - if (!c) - return 0; - af_delay_t* s = af->priv; // Setup for this instance - int nch = c->nch; // Number of channels - int len = mp_audio_psize(c)/c->bps; // Number of sample in data chunk - int ri = 0; - int ch,i; - if (af_make_writeable(af, c) < 0) { - talloc_free(c); - return -1; - } - for(ch=0;ch<nch;ch++){ - switch(c->bps){ - case 1:{ - int8_t* a = c->planes[0]; - int8_t* q = s->q[ch]; - int wi = s->wi[ch]; - ri = s->ri; - for(i=ch;i<len;i+=nch){ - q[wi] = a[i]; - a[i] = q[ri]; - UPDATEQI(wi); - UPDATEQI(ri); - } - s->wi[ch] = wi; - break; - } - case 2:{ - int16_t* a = c->planes[0]; - int16_t* q = s->q[ch]; - int wi = s->wi[ch]; - ri = s->ri; - for(i=ch;i<len;i+=nch){ - q[wi] = a[i]; - a[i] = q[ri]; - UPDATEQI(wi); - UPDATEQI(ri); - } - s->wi[ch] = wi; - break; - } - case 4:{ - int32_t* a = c->planes[0]; - int32_t* q = s->q[ch]; - int wi = s->wi[ch]; - ri = s->ri; - for(i=ch;i<len;i+=nch){ - q[wi] = a[i]; - a[i] = q[ri]; - UPDATEQI(wi); - UPDATEQI(ri); - } - s->wi[ch] = wi; - break; - } - } - } - s->ri = ri; - af_add_output_frame(af, c); - return 0; -} - -// Allocate memory and set function pointers -static int af_open(struct af_instance* af){ - af->control=control; - af->uninit=uninit; - af->filter_frame = filter_frame; - af_delay_t *s = af->priv; - int n = 1; - int i = 0; - char* cl = s->delaystr; - while(cl && n && i < AF_NCH ){ - sscanf(cl,"%f%n",&s->d[i],&n); - if(n==0 || cl[n-1] == '\0') - break; - cl=&cl[n]; - if (*cl != ',') - break; - cl++; - i++; - } - return AF_OK; -} - -#define OPT_BASE_STRUCT af_delay_t -const struct af_info af_info_delay = { - .info = "Delay audio filter", - .name = "delay", - .open = af_open, - .priv_size = sizeof(af_delay_t), - .options = (const struct m_option[]) { - OPT_STRING("delays", delaystr, 0), - {0} - }, -}; diff --git a/audio/filter/af_format.c b/audio/filter/af_format.c index c0fe354a39..748c5cbd52 100644 --- a/audio/filter/af_format.c +++ b/audio/filter/af_format.c @@ -29,10 +29,10 @@ struct priv { int in_format; int in_srate; - struct mp_chmap in_channels; + struct m_channels in_channels; int out_format; int out_srate; - struct mp_chmap out_channels; + struct m_channels out_channels; int fail; }; @@ -44,8 +44,8 @@ static void force_in_params(struct af_instance *af, struct mp_audio *in) if (priv->in_format != AF_FORMAT_UNKNOWN) mp_audio_set_format(in, priv->in_format); - if (priv->in_channels.num) - mp_audio_set_channels(in, &priv->in_channels); + if (priv->in_channels.num_chmaps > 0) + mp_audio_set_channels(in, &priv->in_channels.chmaps[0]); if (priv->in_srate) in->rate = priv->in_srate; @@ -58,8 +58,8 @@ static void force_out_params(struct af_instance *af, struct mp_audio *out) if (priv->out_format != AF_FORMAT_UNKNOWN) mp_audio_set_format(out, priv->out_format); - if (priv->out_channels.num) - mp_audio_set_channels(out, &priv->out_channels); + if (priv->out_channels.num_chmaps > 0) + mp_audio_set_channels(out, &priv->out_channels.chmaps[0]); if (priv->out_srate) out->rate = priv->out_srate; @@ -124,10 +124,10 @@ const struct af_info af_info_format = { .options = (const struct m_option[]) { OPT_AUDIOFORMAT("format", in_format, 0), OPT_INTRANGE("srate", in_srate, 0, 1000, 8*48000), - OPT_CHMAP("channels", in_channels, CONF_MIN, .min = 0), + OPT_CHANNELS("channels", in_channels, 0, .min = 1), OPT_AUDIOFORMAT("out-format", out_format, 0), OPT_INTRANGE("out-srate", out_srate, 0, 1000, 8*48000), - OPT_CHMAP("out-channels", out_channels, CONF_MIN, .min = 0), + OPT_CHANNELS("out-channels", out_channels, 0, .min = 1), OPT_FLAG("fail", fail, 0), {0} }, diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 26c9cbff58..0a7c5d4440 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -33,6 +33,7 @@ #include "config.h" +#include "common/av_common.h" #include "common/common.h" #include "af.h" #include "audio/audio_buffer.h" @@ -57,11 +58,13 @@ typedef struct af_ac3enc_s { struct mp_audio *pending; // unconsumed input data int in_samples; // samples of input per AC3 frame int out_samples; // upper bound on encoded output per AC3 frame + int64_t encoder_buffered; int cfg_add_iec61937_header; int cfg_bit_rate; int cfg_min_channel_num; char *cfg_encoder; + char **cfg_avopts; } af_ac3enc_t; // fmt carries the input format. Change it to the best next-possible format @@ -168,6 +171,7 @@ static int control(struct af_instance *af, int cmd, void *arg) s->in_samples = s->lavc_actx->frame_size; mp_audio_realloc(s->input, s->in_samples); s->input->samples = 0; + s->encoder_buffered = 0; return AF_OK; } case AF_CONTROL_RESET: @@ -176,6 +180,7 @@ static int control(struct af_instance *af, int cmd, void *arg) talloc_free(s->pending); s->pending = NULL; s->input->samples = 0; + s->encoder_buffered = 0; return AF_OK; } return AF_UNKNOWN; @@ -198,8 +203,8 @@ static void uninit(struct af_instance* af) static void update_delay(struct af_instance *af) { af_ac3enc_t *s = af->priv; - af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples) / - (double)s->input->rate; + af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples + + s->encoder_buffered) / (double)s->input->rate; } static int filter_frame(struct af_instance *af, struct mp_audio *audio) @@ -232,6 +237,9 @@ static bool fill_buffer(struct af_instance *af) af->delay = 0; if (s->pending) { + if (!mp_audio_is_writeable(s->input)) + assert(s->input->samples == 0); // we can't have sent a partial frame + mp_audio_realloc_min(s->input, s->in_samples); int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples); s->input->samples += copy; mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy); @@ -249,17 +257,8 @@ static int read_input_frame(struct af_instance *af, AVFrame *frame) if (!fill_buffer(af)) return 0; // need more input - frame->nb_samples = s->in_samples; - frame->format = s->lavc_actx->sample_fmt; - frame->channel_layout = s->lavc_actx->channel_layout; -#if LIBAVUTIL_VERSION_MICRO >= 100 - frame->channels = s->lavc_actx->channels; -#endif - assert(s->input->num_planes <= AV_NUM_DATA_POINTERS); - frame->extended_data = frame->data; - for (int n = 0; n < s->input->num_planes; n++) - frame->data[n] = s->input->planes[n]; - frame->linesize[0] = s->input->samples * s->input->sstride; + if (mp_audio_to_avframe(s->input, frame) < 0) + return -1; return 1; } @@ -268,6 +267,9 @@ static int filter_out(struct af_instance *af) { af_ac3enc_t *s = af->priv; + if (!s->pending) + return 0; + AVFrame *frame = av_frame_alloc(); if (!frame) { MP_FATAL(af, "Could not allocate memory \n"); @@ -295,6 +297,7 @@ static int filter_out(struct af_instance *af) MP_FATAL(af, "Encode failed.\n"); goto done; } + s->encoder_buffered += s->input->samples; s->input->samples = 0; } int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt); @@ -303,6 +306,10 @@ static int filter_out(struct af_instance *af) err = 0; goto done; } + if (lavc_ret < 0) { + MP_FATAL(af, "Encode failed.\n"); + goto done; + } #else err = read_input_frame(af, frame); if (err < 0) @@ -312,7 +319,6 @@ static int filter_out(struct af_instance *af) err = -1; int ok; int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok); - av_frame_free(&frame); s->input->samples = 0; if (lavc_ret < 0 || !ok) { MP_FATAL(af, "Encode failed.\n"); @@ -321,7 +327,9 @@ static int filter_out(struct af_instance *af) #endif MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", - pkt.size, s->pending->samples); + pkt.size, s->pending->samples + s->input->samples); + + s->encoder_buffered -= AC3_FRAME_SIZE; struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); @@ -358,11 +366,12 @@ static int filter_out(struct af_instance *af) swap_16((uint16_t *)(buf + header_len), pkt.size / 2); out->samples = frame_size / out->sstride; af_add_output_frame(af, out); - update_delay(af); err = 0; done: av_packet_unref(&pkt); + av_frame_free(&frame); + update_delay(af); return err; } @@ -385,6 +394,10 @@ static int af_open(struct af_instance* af){ MP_ERR(af, "Audio LAVC, couldn't allocate context!\n"); return AF_ERROR; } + + if (mp_set_avopts(af->log, s->lavc_actx, s->cfg_avopts) < 0) + return AF_ERROR; + // For this one, we require the decoder to expert lists of all supported // parameters. (Not all decoders do that, but the ones we're interested // in do.) @@ -434,6 +447,7 @@ const struct af_info af_info_lavcac3enc = { ({"auto", 0}, {"default", 0})), OPT_INTRANGE("minch", cfg_min_channel_num, 0, 2, 6), OPT_STRING("encoder", cfg_encoder, 0), + OPT_KEYVALUELIST("o", cfg_avopts, 0), {0} }, }; diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index 6fbb445563..fdef69a16b 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -173,12 +173,6 @@ static int check_output_conversion(int mp_format) return af_to_avformat(mp_format); } -bool af_lavrresample_test_conversion(int src_format, int dst_format) -{ - return af_to_avformat(src_format) != AV_SAMPLE_FMT_NONE && - check_output_conversion(dst_format) != AV_SAMPLE_FMT_NONE; -} - static struct mp_chmap fudge_pairs[][2] = { {MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)}, {MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)}, @@ -407,21 +401,6 @@ static int control(struct af_instance *af, int cmd, void *arg) r = configure_lavrr(af, in, out, true); return r; } - case AF_CONTROL_SET_FORMAT: { - int format = *(int *)arg; - if (format && check_output_conversion(format) == AV_SAMPLE_FMT_NONE) - return AF_FALSE; - - mp_audio_set_format(af->data, format); - return AF_OK; - } - case AF_CONTROL_SET_CHANNELS: { - mp_audio_set_channels(af->data, (struct mp_chmap *)arg); - return AF_OK; - } - case AF_CONTROL_SET_RESAMPLE_RATE: - af->data->rate = *(int *)arg; - return AF_OK; case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: { s->playback_speed = *(double *)arg; return AF_OK; diff --git a/audio/filter/af_volume.c b/audio/filter/af_volume.c index 7bd7edd66d..e1d5d45e89 100644 --- a/audio/filter/af_volume.c +++ b/audio/filter/af_volume.c @@ -71,15 +71,19 @@ static int control(struct af_instance *af, int cmd, void *arg) if (af_fmt_is_planar(in->format)) mp_audio_set_format(af->data, af_fmt_to_planar(af->data->format)); s->rgain = 1.0; - if ((s->rgain_track || s->rgain_album) && af->replaygain_data) { - float gain, peak; + struct replaygain_data *rg = af->replaygain_data; + if ((s->rgain_track || s->rgain_album) && rg) { + MP_VERBOSE(af, "Replaygain: Track=%f/%f Album=%f/%f\n", + rg->track_gain, rg->track_peak, + rg->album_gain, rg->album_peak); + float gain, peak; if (s->rgain_track) { - gain = af->replaygain_data->track_gain; - peak = af->replaygain_data->track_peak; + gain = rg->track_gain; + peak = rg->track_peak; } else { - gain = af->replaygain_data->album_gain; - peak = af->replaygain_data->album_peak; + gain = rg->album_gain; + peak = rg->album_peak; } gain += s->rgain_preamp; @@ -115,7 +119,7 @@ static void filter_plane(struct af_instance *af, struct mp_audio *data, int p) { struct priv *s = af->priv; - float level = s->level * s->rgain; + float level = s->level * s->rgain * from_dB(s->cfg_volume, 20.0, -200.0, 60.0); int num_samples = data->samples * data->spf; if (af_fmt_from_planar(af->data->format) == AF_FORMAT_S16) { @@ -158,7 +162,7 @@ static int af_open(struct af_instance *af) struct priv *s = af->priv; af->control = control; af->filter_frame = filter; - s->level = from_dB(s->cfg_volume, 20.0, -200.0, 60.0); + s->level = 1.0; return AF_OK; } |