summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-04 22:07:08 +0100
committerwm4 <wm4@nowhere>2013-12-04 23:13:42 +0100
commit4f581a781bc1c0f82bc4a145b9ea808466aff657 (patch)
tree3d3b66af07bc8d2a2e8502b0e38f2aff19b3f8de
parentad8e3d8c302bd686e811380fe8e47a08a939128c (diff)
downloadmpv-4f581a781bc1c0f82bc4a145b9ea808466aff657.tar.bz2
mpv-4f581a781bc1c0f82bc4a145b9ea808466aff657.tar.xz
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.
-rw-r--r--DOCS/man/en/af.rst23
-rw-r--r--audio/filter/af_channels.c110
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 ``<nch>`` 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:
``<nch>``
number of output channels (1-8)
- ``<nr>``
- number of routes (1-8)
- ``<from1:to1:from2:to2:from3:to3:...>``
- Pairs of numbers between 0 and 7 that define where to route each
- channel.
+ ``<routes>``
+ 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}
+ },
};