From 4f581a781bc1c0f82bc4a145b9ea808466aff657 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 4 Dec 2013 22:07:08 +0100 Subject: af_channels: change options, fix bugs, use option parser Apparently this stopped working after some planar changes (broken format negotiation). Radically change option parsing in an incompatible way. Suggest alternatives to this filter, since it barely has any importance anymore. --- DOCS/man/en/af.rst | 23 ++++++---- audio/filter/af_channels.c | 110 +++++++++++++++++++-------------------------- 2 files changed, 60 insertions(+), 73 deletions(-) diff --git a/DOCS/man/en/af.rst b/DOCS/man/en/af.rst index 34b54eb6c8..bb7f34cf62 100644 --- a/DOCS/man/en/af.rst +++ b/DOCS/man/en/af.rst @@ -184,7 +184,7 @@ Available filters are: Would amplify the sound in the upper and lower frequency region while canceling it almost completely around 1kHz. -``channels=nch[:nr:from1:to1:from2:to2:from3:to3:...]`` +``channels=nch[:routes]`` Can be used for adding, removing, routing and copying audio channels. If only ```` is given, the default routing is used. It works as follows: If the number of output channels is greater than the number of input @@ -195,26 +195,33 @@ Available filters are: ```` number of output channels (1-8) - ```` - number of routes (1-8) - ```` - Pairs of numbers between 0 and 7 that define where to route each - channel. + ```` + List of ``,`` separated routes, in the form ``from1-to1,from2-to2,...``. + Each pair defines where to route each channel. There can be at most + 8 routes. Without this argument, the default routing is used. Since + ``,`` is also used to separate filters, you must quote this argument + with ``[...]`` or similar. .. admonition:: Examples - ``mpv --af=channels=4:4:0:1:1:0:2:2:3:3 media.avi`` + ``mpv --af=channels=4:[0-1,1-0,0-2,1-3] media.avi`` Would change the number of channels to 4 and set up 4 routes that swap channel 0 and channel 1 and leave channel 2 and 3 intact. Observe that if media containing two channels were played back, channels 2 and 3 would contain silence but 0 and 1 would still be swapped. - ``mpv --af=channels=6:4:0:0:0:1:0:2:0:3 media.avi`` + ``mpv --af=channels=6:[0-0,0-1,0-2,0-3] media.avi`` Would change the number of channels to 6 and set up 4 routes that copy channel 0 to channels 0 to 3. Channel 4 and 5 will contain silence. + .. note:: + + You should probably not use this filter. If you want to change the + output channel layout, try the ``format`` filter, which can make mpv + automatically up- and downmix standard channel layouts. + ``format=format:srate:channels:out-format:out-srate:out-channels`` Force a specific audio format/configuration without actually changing the audio data. Keep in mind that the filter system might auto-insert actual diff --git a/audio/filter/af_channels.c b/audio/filter/af_channels.c index d544e4d9c0..b51e8a431e 100644 --- a/audio/filter/af_channels.c +++ b/audio/filter/af_channels.c @@ -35,8 +35,9 @@ typedef struct af_channels_s{ int route[AF_NCH][2]; - int nr; + int nch, nr; int router; + char *routes; }af_channels_t; // Local function for copying data @@ -138,10 +139,12 @@ static int check_routes(af_channels_t* s, int nin, int nout) // Initialization and runtime control static int control(struct af_instance* af, int cmd, void* arg) { - af_channels_t* s = af->setup; + af_channels_t* s = af->priv; switch(cmd){ case AF_CONTROL_REINIT: + mp_audio_set_channels_old(af->data, s->nch); + // Set default channel assignment if(!s->router){ int i; @@ -167,68 +170,19 @@ static int control(struct af_instance* af, int cmd, void* arg) } 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); - mp_audio_force_interleaved_format(af->data); - int r = af_test_output(af,(struct mp_audio*)arg); - if (r != AF_OK) - return r; return check_routes(s,((struct mp_audio*)arg)->nch,af->data->nch); - case AF_CONTROL_COMMAND_LINE:{ - int nch = 0; - int n = 0; - // Check number of channels and number of routing pairs - sscanf(arg, "%i:%i%n", &nch, &s->nr, &n); - - // If router scan commandline for routing pairs - if(s->nr){ - char* cp = &((char*)arg)[n]; - int ch = 0; - // Sanity check - if((s->nr < 1) || (s->nr > AF_NCH)){ - mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be" - " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); - } - s->router = 1; - // Scan for pairs on commandline - while((*cp == ':') && (ch < s->nr)){ - sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); - mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Routing from channel %i to" - " channel %i\n",s->route[ch][FR],s->route[ch][TO]); - cp = &cp[n]; - ch++; - } - } - - struct mp_chmap chmap; - mp_chmap_from_channels(&chmap, nch); - if (AF_OK != af->control(af, AF_CONTROL_SET_CHANNELS, &chmap)) - return AF_ERROR; - return AF_OK; - } - case AF_CONTROL_SET_CHANNELS: - // Reinit must be called after this function has been called - - mp_audio_set_channels(af->data, (struct mp_chmap *)arg); - if(!s->router) - mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Changing number of channels" - " to %i\n",af->data->nch); - return AF_OK; } return AF_UNKNOWN; } -// Deallocate memory -static void uninit(struct af_instance* af) -{ - free(af->setup); -} - // Filter data through filter static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) { struct mp_audio* c = data; // Current working data struct mp_audio* l = af->data; // Local data - af_channels_t* s = af->setup; + af_channels_t* s = af->priv; int i; mp_audio_realloc_min(af->data, data->samples); @@ -243,7 +197,6 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) // Set output data c->planes[0] = l->planes[0]; - c->samples = c->samples / c->nch * l->nch; mp_audio_set_channels(c, &l->channels); return c; @@ -251,18 +204,45 @@ static struct mp_audio* play(struct af_instance* af, struct mp_audio* data) // Allocate memory and set function pointers static int af_open(struct af_instance* af){ - af->control=control; - af->uninit=uninit; - af->play=play; - af->setup=calloc(1,sizeof(af_channels_t)); - if(af->setup == NULL) - return AF_ERROR; - return AF_OK; + af->control=control; + af->play=play; + af_channels_t *s = af->priv; + + // If router scan commandline for routing pairs + if(s->routes && s->routes[0]){ + char* cp = s->routes; + int ch = 0; + // Scan for pairs on commandline + do { + int n = 0; + if (ch >= AF_NCH) { + mp_msg(MSGT_AFILTER, MSGL_FATAL, + "[channels] Can't have more than %d routes.\n", AF_NCH); + return AF_ERROR; + } + sscanf(cp, "%i-%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); + mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Routing from channel %i to" + " channel %i\n",s->route[ch][FR],s->route[ch][TO]); + cp = &cp[n]; + ch++; + } while(*cp == ',' && *(cp++)); + s->nr = ch; + if (s->nr > 0) + s->router = 1; + } + + return AF_OK; } -// Description of this filter +#define OPT_BASE_STRUCT af_channels_t struct af_info af_info_channels = { - .info = "Insert or remove channels", - .name = "channels", - .open = af_open, + .info = "Insert or remove channels", + .name = "channels", + .open = af_open, + .priv_size = sizeof(af_channels_t), + .options = (const struct m_option[]) { + OPT_INTRANGE("nch", nch, 0, 1, AF_NCH, OPTDEF_INT(2)), + OPT_STRING("routes", routes, 0), + {0} + }, }; -- cgit v1.2.3