Commit 147717df authored by Thomas Guillem's avatar Thomas Guillem

audio_filter: only one module for all simple channel mixers

This fixes a bad conversion when doing 6_x to 2_0 using neon.

The neon channel mixer code is now used from the simple channel_mixer module.
parent e5a8ac37
neondir = $(pluginsdir)/arm_neon
libsimple_channel_mixer_neon_plugin_la_SOURCES = \
arm_neon/simple_channel_mixer.S \
arm_neon/simple_channel_mixer.c
libsimple_channel_mixer_neon_plugin_la_CFLAGS = $(AM_CFLAGS)
libsimple_channel_mixer_neon_plugin_LIBTOOLFLAGS = --tag=CC
libchroma_yuv_neon_plugin_la_SOURCES = \
arm_neon/deinterleave_chroma.S \
arm_neon/i420_yuyv.S \
......@@ -30,7 +24,6 @@ libyuv_rgb_neon_plugin_LIBTOOLFLAGS = --tag=CC
if HAVE_NEON
neon_LTLIBRARIES = \
libsimple_channel_mixer_neon_plugin.la \
libchroma_yuv_neon_plugin.la \
libvolume_neon_plugin.la \
libyuv_rgb_neon_plugin.la
......
......@@ -34,9 +34,9 @@ coeff_7to2:
.float 0.5
.float 0.25
.float 0.25
.global convert_7to2_neon_asm
.type convert_7to2_neon_asm, %function
convert_7to2_neon_asm:
.global convert_7_x_to_2_0_neon_asm
.type convert_7_x_to_2_0_neon_asm, %function
convert_7_x_to_2_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_7to2
......@@ -70,9 +70,9 @@ coeff_5to2:
.float 0.5
.float 0.33
.float 0.33
.global convert_5to2_neon_asm
.type convert_5to2_neon_asm, %function
convert_5to2_neon_asm:
.global convert_5_x_to_2_0_neon_asm
.type convert_5_x_to_2_0_neon_asm, %function
convert_5_x_to_2_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_5to2
......@@ -100,9 +100,9 @@ convert_5to2_neon_asm:
coeff_4to2:
.float 0.5
.float 0.5
.global convert_4to2_neon_asm
.type convert_4to2_neon_asm, %function
convert_4to2_neon_asm:
.global convert_4_0_to_2_0_neon_asm
.type convert_4_0_to_2_0_neon_asm, %function
convert_4_0_to_2_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_4to2
......@@ -124,9 +124,9 @@ convert_4to2_neon_asm:
coeff_3to2:
.float 0.5
.float 0.5
.global convert_3to2_neon_asm
.type convert_3to2_neon_asm, %function
convert_3to2_neon_asm:
.global convert_3_x_to_2_0_neon_asm
.type convert_3_x_to_2_0_neon_asm, %function
convert_3_x_to_2_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_3to2
......@@ -154,9 +154,9 @@ coeff_7to1:
.float 0.25
.float 0.125
.float 0.125
.global convert_7to1_neon_asm
.type convert_7to1_neon_asm, %function
convert_7to1_neon_asm:
.global convert_7_x_to_1_0_neon_asm
.type convert_7_x_to_1_0_neon_asm, %function
convert_7_x_to_1_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_7to1
......@@ -188,9 +188,9 @@ coeff_5to1:
.float 0.25
.float 0.16666667
.float 0.16666667
.global convert_5to1_neon_asm
.type convert_5to1_neon_asm, %function
convert_5to1_neon_asm:
.global convert_5_x_to_1_0_neon_asm
.type convert_5_x_to_1_0_neon_asm, %function
convert_5_x_to_1_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_5to1
......@@ -219,9 +219,9 @@ coeff_7to4:
.float 0.5
.float 0.16666667
.float 0.16666667
.global convert_7to4_neon_asm
.type convert_7to4_neon_asm, %function
convert_7to4_neon_asm:
.global convert_7_x_to_4_0_neon_asm
.type convert_7_x_to_4_0_neon_asm, %function
convert_7_x_to_4_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_7to4
......@@ -252,9 +252,9 @@ convert_7to4_neon_asm:
coeff_5to4:
.float 0.5
.float 0.5
.global convert_5to4_neon_asm
.type convert_5to4_neon_asm, %function
convert_5to4_neon_asm:
.global convert_5_x_to_4_0_neon_asm
.type convert_5_x_to_4_0_neon_asm, %function
convert_5_x_to_4_0_neon_asm:
push {r4,lr}
adr COEFF, coeff_5to4
......
/*****************************************************************************
* simple_channel_mixer.c : simple channel mixer plug-in using NEON assembly
*****************************************************************************
* Copyright (C) 2002, 2004, 2006-2009, 2012 VLC authors and VideoLAN
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* David Geldreich <david.geldreich@free.fr>
* Sébastien Toque
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_filter.h>
#include <vlc_block.h>
#include <vlc_cpu.h>
#include <assert.h>
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static int OpenFilter( vlc_object_t * );
vlc_module_begin ()
set_description( N_("Audio filter for simple channel mixing using NEON assembly") )
set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_MISC )
set_capability( "audio converter", 20 )
set_callbacks( OpenFilter, NULL )
vlc_module_end ()
#define FILTER_WRAPPER(in, out) \
void convert_##in##to##out##_neon_asm(float *dst, const float *src, int num, bool lfeChannel); \
static block_t *Filter_##in##to##out (filter_t *p_filter, block_t *p_block) \
{ \
block_t *p_out; \
if (!FilterInit( p_filter, p_block, &p_out )) \
return NULL; \
const float *p_src = (const float *)p_block->p_buffer; \
float *p_dest = (float *)p_out->p_buffer; \
convert_##in##to##out##_neon_asm( p_dest, p_src, p_block->i_nb_samples, \
p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ); \
block_Release( p_block ); \
return p_out; \
}
#define TRY_FILTER(in, out) \
if ( b_input_##in && b_output_##out ) \
{ \
p_filter->pf_audio_filter = Filter_##in##to##out ; \
return VLC_SUCCESS; \
}
/*****************************************************************************
* Filter:
*****************************************************************************/
static bool FilterInit( filter_t *p_filter, block_t *p_block, block_t **pp_out )
{
if( !p_block || !p_block->i_nb_samples )
{
if( p_block )
block_Release( p_block );
return false;
}
size_t i_out_size = p_block->i_nb_samples *
p_filter->fmt_out.audio.i_bitspersample *
p_filter->fmt_out.audio.i_channels / 8;
block_t *p_out = block_Alloc( i_out_size );
if( !p_out )
{
msg_Warn( p_filter, "can't get output buffer" );
block_Release( p_block );
return false;
}
p_out->i_nb_samples = p_block->i_nb_samples;
p_out->i_dts = p_block->i_dts;
p_out->i_pts = p_block->i_pts;
p_out->i_length = p_block->i_length;
int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
p_out->i_buffer = p_block->i_buffer * i_output_nb / i_input_nb;
*pp_out = p_out;
return true;
}
FILTER_WRAPPER(7,2)
FILTER_WRAPPER(5,2)
FILTER_WRAPPER(4,2)
FILTER_WRAPPER(3,2)
FILTER_WRAPPER(7,1)
FILTER_WRAPPER(5,1)
FILTER_WRAPPER(7,4)
FILTER_WRAPPER(5,4)
/*****************************************************************************
* OpenFilter:
*****************************************************************************/
static int OpenFilter( vlc_object_t *p_this )
{
filter_t *p_filter = (filter_t *)p_this;
if (!vlc_CPU_ARM_NEON())
return VLC_EGENERIC;
audio_format_t fmt_in = p_filter->fmt_in.audio;
audio_format_t fmt_out = p_filter->fmt_out.audio;
fmt_in.i_format = p_filter->fmt_in.i_codec;
fmt_out.i_format = p_filter->fmt_out.i_codec;
if( fmt_in.i_format != VLC_CODEC_FL32 ||
fmt_in.i_format != fmt_out.i_format ||
fmt_in.i_rate != fmt_out.i_rate )
{
return VLC_EGENERIC;
}
if( fmt_in.i_physical_channels == fmt_out.i_physical_channels &&
fmt_in.i_original_channels == fmt_out.i_original_channels )
{
return VLC_EGENERIC;
}
const bool b_input_7 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_7_0;
const bool b_input_5 = ( (fmt_in.i_physical_channels & AOUT_CHANS_5_0) == AOUT_CHANS_5_0 ||
(fmt_in.i_physical_channels & AOUT_CHANS_5_0_MIDDLE) == AOUT_CHANS_5_0_MIDDLE );
const bool b_input_4 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_4_CENTER_REAR;
const bool b_input_3 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_3_0;
const bool b_output_1 = fmt_out.i_physical_channels == AOUT_CHAN_CENTER;
const bool b_output_2 = fmt_out.i_physical_channels == AOUT_CHANS_2_0;
const bool b_output_4 = fmt_out.i_physical_channels == AOUT_CHANS_4_0;
/* Only conversion to Mono, Stereo and 4.0 right now */
/* Only from 7/7.1/5/5.1/3/3.1/2.0
* XXX 5.X rear and middle are handled the same way */
TRY_FILTER(7,2)
TRY_FILTER(5,2)
TRY_FILTER(4,2)
TRY_FILTER(3,2)
TRY_FILTER(7,1)
TRY_FILTER(5,1)
TRY_FILTER(7,4)
TRY_FILTER(5,4)
return VLC_EGENERIC;
}
......@@ -56,6 +56,9 @@ libtrivial_channel_mixer_plugin_la_SOURCES = \
audio_filter/channel_mixer/trivial.c
libsimple_channel_mixer_plugin_la_SOURCES = \
audio_filter/channel_mixer/simple.c
if HAVE_NEON
libsimple_channel_mixer_plugin_la_SOURCES += arm_neon/simple_channel_mixer.S
endif
audio_filter_LTLIBRARIES += \
libdolby_surround_decoder_plugin.la \
......
......@@ -258,6 +258,12 @@ static void DoWork_6_1_to_5_x( filter_t * p_filter, block_t * p_in_buf, block_t
}
}
#if defined (__arm__)
#include "simple_neon.h"
#define GET_WORK(in, out) GET_WORK_##in##_to_##out##_neon()
#else
#define GET_WORK(in, out) DoWork_##in##_to_##out
#endif
/*****************************************************************************
* OpenFilter:
......@@ -300,43 +306,43 @@ static int OpenFilter( vlc_object_t *p_this )
if( output == AOUT_CHAN_CENTER )
{
if( b_input_7_x )
do_work = DoWork_7_x_to_1_0;
do_work = GET_WORK(7_x,1_0);
else if( b_input_5_x )
do_work = DoWork_5_x_to_1_0;
do_work = GET_WORK(5_x,1_0);
else if( b_input_4_center_rear )
do_work = DoWork_4_0_to_1_0;
do_work = GET_WORK(4_0,1_0);
else if( b_input_3_x )
do_work = DoWork_3_x_to_1_0;
do_work = GET_WORK(3_x,1_0);
else
do_work = DoWork_2_x_to_1_0;
do_work = GET_WORK(2_x,1_0);
}
else if( output == AOUT_CHANS_2_0 )
{
if( b_input_7_x )
do_work = DoWork_7_x_to_2_0;
do_work = GET_WORK(7_x,2_0);
else if( b_input_6_1 )
do_work = DoWork_6_1_to_2_0;
do_work = GET_WORK(6_1,2_0);
else if( b_input_5_x )
do_work = DoWork_5_x_to_2_0;
do_work = GET_WORK(5_x,2_0);
else if( b_input_4_center_rear )
do_work = DoWork_4_0_to_2_0;
do_work = GET_WORK(4_0,2_0);
else if( b_input_3_x )
do_work = DoWork_3_x_to_2_0;
do_work = GET_WORK(3_x,2_0);
}
else if( output == AOUT_CHANS_4_0 )
{
if( b_input_7_x )
do_work = DoWork_7_x_to_4_0;
do_work = GET_WORK(7_x,4_0);
else if( b_input_5_x )
do_work = DoWork_5_x_to_4_0;
do_work = GET_WORK(5_x,4_0);
}
else if( (output & ~AOUT_CHAN_LFE) == AOUT_CHANS_5_0 ||
(output & ~AOUT_CHAN_LFE) == AOUT_CHANS_5_0_MIDDLE )
{
if( b_input_7_x )
do_work = DoWork_7_x_to_5_x;
do_work = GET_WORK(7_x,5_x);
else if( b_input_6_1 )
do_work = DoWork_6_1_to_5_x;
do_work = GET_WORK(6_1,5_x);
}
if( do_work == NULL )
......
/*****************************************************************************
* simple_neon.h : simple channel mixer plug-in using NEON assembly
*****************************************************************************
* Copyright (C) 2002, 2004, 2006-2009, 2012, 2015 VLC authors and VideoLAN
* $Id$
*
* Authors: Gildas Bazin <gbazin@videolan.org>
* David Geldreich <david.geldreich@free.fr>
* Sébastien Toque
* Thomas Guillem <thomas@gllm.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_cpu.h>
/* Only conversion to Mono, Stereo and 4.0 right now */
/* Only from 7/7.1/5/5.1/3/3.1/2.0
* XXX 5.X rear and middle are handled the same way */
#define NEON_WRAPPER(in, out) \
void convert_##in##_to_##out##_neon_asm(float *dst, const float *src, int num, bool lfeChannel); \
static inline void DoWork_##in##_to_##out##_neon( filter_t *p_filter, block_t *p_in_buf, block_t *p_out_buf ) \
{ \
const float *p_src = (const float *)p_in_buf->p_buffer; \
float *p_dest = (float *)p_out_buf->p_buffer; \
convert_##in##_to_##out##_neon_asm( p_dest, p_src, p_in_buf->i_nb_samples, \
p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ); \
} \
static inline void (*GET_WORK_##in##_to_##out##_neon())(filter_t*, block_t*, block_t*) \
{ \
return vlc_CPU_ARM_NEON() ? DoWork_##in##_to_##out##_neon : DoWork_##in##_to_##out; \
}
NEON_WRAPPER(7_x,2_0)
NEON_WRAPPER(5_x,2_0)
NEON_WRAPPER(4_0,2_0)
NEON_WRAPPER(3_x,2_0)
NEON_WRAPPER(7_x,1_0)
NEON_WRAPPER(5_x,1_0)
NEON_WRAPPER(7_x,4_0)
NEON_WRAPPER(5_x,4_0)
/* TODO: the following conversions are not handled in NEON */
#define C_WRAPPER(in, out) \
static inline void (*GET_WORK_##in##_to_##out##_neon())(filter_t*, block_t*, block_t*) \
{ \
return DoWork_##in##_to_##out; \
}
C_WRAPPER(4_0,1_0)
C_WRAPPER(3_x,1_0)
C_WRAPPER(2_x,1_0)
C_WRAPPER(6_1,2_0)
C_WRAPPER(7_x,5_x)
C_WRAPPER(6_1,5_x)
......@@ -279,7 +279,6 @@ modules/access/vnc.c
modules/access/wasapi.c
modules/access/zip/zipstream.c
modules/arm_neon/chroma_yuv.c
modules/arm_neon/simple_channel_mixer.c
modules/arm_neon/volume.c
modules/arm_neon/yuv_rgb.c
modules/audio_filter/audiobargraph_a.c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment