1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-22 14:52:43 +00:00

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.
This commit is contained in:
wm4 2013-12-04 22:07:08 +01:00
parent ad8e3d8c30
commit 4f581a781b
2 changed files with 60 additions and 73 deletions

View File

@ -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

View File

@ -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}
},
};