X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Fcommon.c;h=9c05ac50e23ab7d2f3eadef14291367f811de593;hb=a308b7a17466bb91908a518c93b36dacb49212e7;hp=93b6a0dd95b862f82c20d0dcbf605ad50c932c4e;hpb=51087cc213962a3135b820571a9847b995e21d5f;p=vlc diff --git a/src/audio_output/common.c b/src/audio_output/common.c index 93b6a0dd95..9c05ac50e2 100644 --- a/src/audio_output/common.c +++ b/src/audio_output/common.c @@ -69,7 +69,6 @@ unsigned int aout_BitsPerSample( vlc_fourcc_t i_format ) case VLC_CODEC_S32B: case VLC_CODEC_F32L: case VLC_CODEC_F32B: - case VLC_CODEC_FI32: return 32; case VLC_CODEC_F64L: @@ -279,128 +278,140 @@ unsigned aout_CheckChannelReorder( const uint32_t *chans_in, /** * Reorders audio samples within a block of linear audio interleaved samples. * \param ptr start address of the block of samples - * \param bytes size of the block in bytes (must be a multiple of the product of the - * channels count and the sample size) + * \param bytes size of the block in bytes (must be a multiple of the product + * of the channels count and the sample size) * \param channels channels count (also length of the chans_table table) * \param chans_table permutation table to reorder the channels * (usually computed by aout_CheckChannelReorder()) * \param fourcc sample format (must be a linear sample format) * \note The samples must be naturally aligned in memory. */ -void aout_ChannelReorder( void *ptr, size_t bytes, unsigned channels, +void aout_ChannelReorder( void *ptr, size_t bytes, uint8_t channels, const uint8_t *restrict chans_table, vlc_fourcc_t fourcc ) { + if( unlikely(bytes == 0) ) + return; + assert( channels != 0 ); - assert( channels <= AOUT_CHAN_MAX ); - /* The audio formats supported in audio output are inlined. For other formats (used in - * demuxers and muxers), memcpy() is used to avoid breaking type punning. */ - switch( fourcc ) + /* The audio formats supported in audio output are inlined. For other + * formats (used in demuxers and muxers), memcpy() is used to avoid + * breaking type punning. */ +#define REORDER_TYPE(type) \ +do { \ + const size_t frames = (bytes / sizeof (type)) / channels; \ + type *buf = ptr; \ +\ + for( size_t i = 0; i < frames; i++ ) \ + { \ + type tmp[AOUT_CHAN_MAX]; \ +\ + for( size_t j = 0; j < channels; j++ ) \ + tmp[chans_table[j]] = buf[j]; \ + memcpy( buf, tmp, sizeof (type) * channels ); \ + buf += channels; \ + } \ +} while(0) + + if( likely(channels <= AOUT_CHAN_MAX) ) { - case VLC_CODEC_FL32: - { - const size_t frames = (bytes / 4) / channels; - float *buf = ptr; - - for( size_t i = 0; i < frames; i++ ) - { - float tmp[AOUT_CHAN_MAX]; - - for( size_t j = 0; j < channels; j++ ) - tmp[chans_table[j]] = buf[j]; - memcpy( buf, tmp, 4 * channels ); - buf += channels; - } - break; - } - - case VLC_CODEC_S16N: + switch( fourcc ) { - const size_t frames = (bytes / 2) / channels; - int16_t *buf = ptr; - - for( size_t i = 0; i < frames; i++ ) - { - int16_t tmp[AOUT_CHAN_MAX]; - - for( size_t j = 0; j < channels; j++ ) - tmp[chans_table[j]] = buf[j]; - memcpy( buf, tmp, 2 * channels ); - buf += channels; - } - break; + case VLC_CODEC_U8: REORDER_TYPE(uint8_t); return; + case VLC_CODEC_S16N: REORDER_TYPE(int16_t); return; + case VLC_CODEC_FL32: REORDER_TYPE(float); return; + case VLC_CODEC_S32N: REORDER_TYPE(int32_t); return; + case VLC_CODEC_FL64: REORDER_TYPE(double); return; } + } - case VLC_CODEC_FL64: - { - const size_t frames = (bytes / 8) / channels; - double *buf = ptr; - - for( size_t i = 0; i < frames; i++ ) - { - double tmp[AOUT_CHAN_MAX]; - - for( size_t j = 0; j < channels; j++ ) - tmp[chans_table[j]] = buf[j]; - memcpy( buf, tmp, 8 * channels ); - buf += channels; - } - break; - } - - case VLC_CODEC_S32N: - { - const size_t frames = (bytes / 4) / channels; - int32_t *buf = ptr; - - for( size_t i = 0; i < frames; i++ ) - { - int32_t tmp[AOUT_CHAN_MAX]; + unsigned size = aout_BitsPerSample( fourcc ) / 8; + assert( size != 0 && size <= 8 ); - for( size_t j = 0; j < channels; j++ ) - tmp[chans_table[j]] = buf[j]; - memcpy( buf, tmp, 4 * channels ); - buf += channels; - } - break; - } + const size_t frames = bytes / (size * channels); + unsigned char *buf = ptr; - case VLC_CODEC_U8: - { - const size_t frames = bytes / channels; - uint8_t *buf = ptr; + for( size_t i = 0; i < frames; i++ ) + { + unsigned char tmp[256 * 8]; - for( size_t i = 0; i < frames; i++ ) - { - uint8_t tmp[AOUT_CHAN_MAX]; + for( size_t j = 0; j < channels; j++ ) + memcpy( tmp + size * chans_table[j], buf + size * j, size ); + memcpy( buf, tmp, size * channels ); + buf += size * channels; + } +} - for( size_t j = 0; j < channels; j++ ) - tmp[chans_table[j]] = buf[j]; - memcpy( buf, tmp, channels ); - buf += channels; - } - break; - } +/** + * Interleaves audio samples within a block of samples. + * \param dst destination buffer for interleaved samples + * \param srcv source buffers (one per plane) of uninterleaved samples + * \param samples number of samples (per channel/per plane) + * \param chans channels/planes count + * \param fourcc sample format (must be a linear sample format) + * \note The samples must be naturally aligned in memory. + * \warning Destination and source buffers MUST NOT overlap. + */ +void aout_Interleave( void *restrict dst, const void *const *srcv, + unsigned samples, unsigned chans, vlc_fourcc_t fourcc ) +{ +#define INTERLEAVE_TYPE(type) \ +do { \ + type *d = dst; \ + for( size_t i = 0; i < chans; i++ ) { \ + const type *s = srcv[i]; \ + for( size_t j = 0, k = 0; j < samples; j++, k += chans ) \ + d[k] = *(s++); \ + d++; \ + } \ +} while(0) - default: - { - unsigned size = aout_BitsPerSample( fourcc ) / 8; - const size_t frames = bytes / size; - unsigned char *buf = ptr; + switch( fourcc ) + { + case VLC_CODEC_U8: INTERLEAVE_TYPE(uint8_t); break; + case VLC_CODEC_S16N: INTERLEAVE_TYPE(uint16_t); break; + case VLC_CODEC_FL32: INTERLEAVE_TYPE(float); break; + case VLC_CODEC_S32N: INTERLEAVE_TYPE(int32_t); break; + case VLC_CODEC_FL64: INTERLEAVE_TYPE(double); break; + default: vlc_assert_unreachable(); + } +#undef INTERLEAVE_TYPE +} - assert( bytes != 0 ); - for( size_t i = 0; i < frames; i++ ) - { - unsigned char tmp[AOUT_CHAN_MAX * bytes]; +/** + * Deinterleaves audio samples within a block of samples. + * \param dst destination buffer for planar samples + * \param src source buffer with interleaved samples + * \param samples number of samples (per channel/per plane) + * \param chans channels/planes count + * \param fourcc sample format (must be a linear sample format) + * \note The samples must be naturally aligned in memory. + * \warning Destination and source buffers MUST NOT overlap. + */ +void aout_Deinterleave( void *restrict dst, const void *restrict src, + unsigned samples, unsigned chans, vlc_fourcc_t fourcc ) +{ +#define DEINTERLEAVE_TYPE(type) \ +do { \ + type *d = dst; \ + const type *s = src; \ + for( size_t i = 0; i < chans; i++ ) { \ + for( size_t j = 0, k = 0; j < samples; j++, k += chans ) \ + *(d++) = s[k]; \ + s++; \ + } \ +} while(0) - for( size_t j = 0; j < channels; j++ ) - memcpy( tmp + size * chans_table[j], buf + size * j, size ); - memcpy( buf, tmp, size * channels ); - buf += size * channels; - } - break; - } + switch( fourcc ) + { + case VLC_CODEC_U8: DEINTERLEAVE_TYPE(uint8_t); break; + case VLC_CODEC_S16N: DEINTERLEAVE_TYPE(uint16_t); break; + case VLC_CODEC_FL32: DEINTERLEAVE_TYPE(float); break; + case VLC_CODEC_S32N: DEINTERLEAVE_TYPE(int32_t); break; + case VLC_CODEC_FL64: DEINTERLEAVE_TYPE(double); break; + default: vlc_assert_unreachable(); } +#undef DEINTERLEAVE_TYPE } /***************************************************************************** @@ -520,7 +531,7 @@ static int FilterOrder( const char *psz_name ) return INT_MAX; } -/* This function will add or remove a a module from a string list (colon +/* This function will add or remove a module from a string list (colon * separated). It will return true if there is a modification * In case p_aout is NULL, we will use configuration instead of variable */ bool aout_ChangeFilterString( vlc_object_t *p_obj, vlc_object_t *p_aout,