X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Fcommon.c;h=fde38b3ab78a159d08996192c18102ea87767fa8;hb=14f37b2101842fa6e427f962f689db74eff6faba;hp=e3bbb06838558096959a79f40e8db5d449ac1060;hpb=6da58d2af63c541668ff4b50774b3dc2c10a12e8;p=vlc diff --git a/src/audio_output/common.c b/src/audio_output/common.c index e3bbb06838..fde38b3ab7 100644 --- a/src/audio_output/common.c +++ b/src/audio_output/common.c @@ -33,6 +33,7 @@ #include #include #include "aout_internal.h" +#include "libvlc.h" /* * Instances management (internal and external) @@ -143,27 +144,29 @@ unsigned int aout_BitsPerSample( vlc_fourcc_t i_format ) { switch( i_format ) { - case VLC_FOURCC('u','8',' ',' '): - case VLC_FOURCC('s','8',' ',' '): + case VLC_CODEC_U8: + case VLC_CODEC_S8: return 8; - case VLC_FOURCC('u','1','6','l'): - case VLC_FOURCC('s','1','6','l'): - case VLC_FOURCC('u','1','6','b'): - case VLC_FOURCC('s','1','6','b'): + case VLC_CODEC_U16L: + case VLC_CODEC_S16L: + case VLC_CODEC_U16B: + case VLC_CODEC_S16B: return 16; - case VLC_FOURCC('u','2','4','l'): - case VLC_FOURCC('s','2','4','l'): - case VLC_FOURCC('u','2','4','b'): - case VLC_FOURCC('s','2','4','b'): + case VLC_CODEC_U24L: + case VLC_CODEC_S24L: + case VLC_CODEC_U24B: + case VLC_CODEC_S24B: return 24; - case VLC_FOURCC('f','l','3','2'): - case VLC_FOURCC('f','i','3','2'): + case VLC_CODEC_S32L: + case VLC_CODEC_S32B: + case VLC_CODEC_FL32: + case VLC_CODEC_FI32: return 32; - case VLC_FOURCC('f','l','6','4'): + case VLC_CODEC_FL64: return 64; default: @@ -233,9 +236,15 @@ const char * aout_FormatPrintChannels( const audio_sample_format_t * p_format ) case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT: return "2F2R"; + case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT + | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT: + return "2F2M"; case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT: return "3F2R"; + case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER + | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT: + return "3F2M"; case AOUT_CHAN_CENTER | AOUT_CHAN_LFE: if ( (p_format->i_original_channels & AOUT_CHAN_CENTER) @@ -268,9 +277,15 @@ const char * aout_FormatPrintChannels( const audio_sample_format_t * p_format ) case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE: return "2F2R/LFE"; + case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT + | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE: + return "2F2M/LFE"; case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE: return "3F2R/LFE"; + case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER + | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE: + return "3F2M/LFE"; case AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT: @@ -512,7 +527,8 @@ mtime_t aout_DateGet( const audio_date_t * p_date ) *****************************************************************************/ mtime_t aout_DateIncrement( audio_date_t * p_date, uint32_t i_nb_samples ) { - mtime_t i_dividend = (mtime_t)i_nb_samples * 1000000; + mtime_t i_dividend = INT64_C(1000000) * i_nb_samples; + assert( p_date->i_divider > 0 ); /* uninitialized audio_data_t ? */ p_date->date += i_dividend / p_date->i_divider; p_date->i_remainder += (int)(i_dividend % p_date->i_divider); if ( p_date->i_remainder >= p_date->i_divider ) @@ -535,7 +551,13 @@ int aout_CheckChannelReorder( const uint32_t *pi_chan_order_in, bool b_chan_reorder = false; int i, j, k, l; - if( i_channels > AOUT_CHAN_MAX ) return false; + if( i_channels > AOUT_CHAN_MAX ) + return false; + + if( pi_chan_order_in == NULL ) + pi_chan_order_in = pi_vlc_chan_order_wg4; + if( pi_chan_order_out == NULL ) + pi_chan_order_out = pi_vlc_chan_order_wg4; for( i = 0, j = 0; pi_chan_order_in[i]; i++ ) { @@ -626,3 +648,105 @@ void aout_ChannelReorder( uint8_t *p_buf, int i_buffer, } } } + +/***************************************************************************** + * aout_ChannelExtract: + *****************************************************************************/ +static inline void ExtractChannel( uint8_t *pi_dst, int i_dst_channels, + const uint8_t *pi_src, int i_src_channels, + int i_sample_count, + const int *pi_selection, int i_bytes ) +{ + for( int i = 0; i < i_sample_count; i++ ) + { + for( int j = 0; j < i_dst_channels; j++ ) + memcpy( &pi_dst[j * i_bytes], &pi_src[pi_selection[j] * i_bytes], i_bytes ); + pi_dst += i_dst_channels * i_bytes; + pi_src += i_src_channels * i_bytes; + } +} + +void aout_ChannelExtract( void *p_dst, int i_dst_channels, + const void *p_src, int i_src_channels, + int i_sample_count, const int *pi_selection, int i_bits_per_sample ) +{ + /* It does not work in place */ + assert( p_dst != p_src ); + + /* Force the compiler to inline for the specific cases so it can optimize */ + if( i_bits_per_sample == 8 ) + ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 1 ); + else if( i_bits_per_sample == 16 ) + ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 2 ); + else if( i_bits_per_sample == 24 ) + ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 3 ); + else if( i_bits_per_sample == 32 ) + ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 4 ); + else if( i_bits_per_sample == 64 ) + ExtractChannel( p_dst, i_dst_channels, p_src, i_src_channels, i_sample_count, pi_selection, 8 ); +} + +bool aout_CheckChannelExtraction( int *pi_selection, + uint32_t *pi_layout, int *pi_channels, + const uint32_t pi_order_dst[AOUT_CHAN_MAX], + const uint32_t *pi_order_src, int i_channels ) +{ + const uint32_t pi_order_dual_mono[] = { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT }; + uint32_t i_layout = 0; + int i_out = 0; + int pi_index[AOUT_CHAN_MAX]; + + /* */ + if( !pi_order_dst ) + pi_order_dst = pi_vlc_chan_order_wg4; + + /* Detect special dual mono case */ + if( i_channels == 2 && + pi_order_src[0] == AOUT_CHAN_CENTER && pi_order_src[1] == AOUT_CHAN_CENTER ) + { + i_layout |= AOUT_CHAN_DUALMONO; + pi_order_src = pi_order_dual_mono; + } + + /* */ + for( int i = 0; i < i_channels; i++ ) + { + /* Ignore unknown or duplicated channels or not present in output */ + if( !pi_order_src[i] || (i_layout & pi_order_src[i]) ) + continue; + + for( int j = 0; j < AOUT_CHAN_MAX; j++ ) + { + if( pi_order_dst[j] == pi_order_src[i] ) + { + assert( i_out < AOUT_CHAN_MAX ); + pi_index[i_out++] = i; + i_layout |= pi_order_src[i]; + break; + } + } + } + + /* */ + for( int i = 0, j = 0; i < AOUT_CHAN_MAX; i++ ) + { + for( int k = 0; k < i_out; k++ ) + { + if( pi_order_dst[i] == pi_order_src[pi_index[k]] ) + { + pi_selection[j++] = pi_index[k]; + break; + } + } + } + + *pi_layout = i_layout; + *pi_channels = i_out; + + for( int i = 0; i < i_out; i++ ) + { + if( pi_selection[i] != i ) + return true; + } + return i_out == i_channels; +}