]> git.sesse.net Git - vlc/commitdiff
aout: pass FOURCC instead of bits to aout_ChannelsReorder()
authorRémi Denis-Courmont <remi@remlab.net>
Thu, 20 Dec 2012 19:28:01 +0000 (21:28 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Thu, 20 Dec 2012 19:29:39 +0000 (21:29 +0200)
To fix type aliasing, we need to know whether the data is float or integer,
or use only char pointers.

Also add support for FL64 and arbitrary lengths.

include/vlc_aout.h
modules/audio_output/alsa.c
modules/audio_output/auhal.c
modules/audio_output/directx.c
modules/audio_output/wasapi.c
modules/audio_output/waveout.c
modules/demux/wav.c
modules/mux/wav.c
src/audio_output/common.c

index de9986a9427ad8d31b80de940123acfb0b723f87..77bbd7f10aab8d6f8c2101ccc25b5fcffb9e6d82 100644 (file)
@@ -236,7 +236,7 @@ static const uint32_t pi_vlc_chan_order_wg4[] =
  */
 VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *,
                                            uint32_t mask, uint8_t *table );
-VLC_API void aout_ChannelReorder( void *, size_t, unsigned, const uint8_t *, unsigned );
+VLC_API void aout_ChannelReorder(void *, size_t, unsigned, const uint8_t *, vlc_fourcc_t);
 
 /**
  * This fonction will compute the extraction parameter into pi_selection to go
index cd0a59391efbb72ada3cac5dddb5ddd9ccedd056..240dcdd170032a2ca04b812a757a32f53b7a2177 100644 (file)
@@ -44,9 +44,9 @@ struct aout_sys_t
 {
     snd_pcm_t *pcm;
     unsigned rate; /**< Sample rate */
+    vlc_fourcc_t format; /**< Sample format */
     uint8_t chans_table[AOUT_CHAN_MAX]; /**< Channels order table */
     uint8_t chans_to_reorder; /**< Number of channels to reorder */
-    uint8_t bits; /**< Bits per sample per channel */
 
     bool soft_mute;
     float soft_gain;
@@ -563,11 +563,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
         fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
         fmt->i_frame_length = A52_FRAME_NB;
     }
-    else
-    {
-        aout_FormatPrepare (fmt);
-        sys->bits = fmt->i_bitspersample;
-    }
+    sys->format = fmt->i_format;
 
     aout->time_get = TimeGet;
     aout->play = Play;
@@ -611,7 +607,7 @@ static void Play (audio_output_t *aout, block_t *block)
 
     if (sys->chans_to_reorder != 0)
         aout_ChannelReorder(block->p_buffer, block->i_buffer,
-                           sys->chans_to_reorder, sys->chans_table, sys->bits);
+                           sys->chans_to_reorder, sys->chans_table, sys->format);
 
     snd_pcm_t *pcm = sys->pcm;
 
index 5ef97761a4d7edb472cd49c0257f4c922895f035..bd059090f3b185d31b6799ae4c21cd78e48e7210 100644 (file)
@@ -1222,7 +1222,7 @@ static void PlayAnalog (audio_output_t * p_aout, block_t * p_block)
                                p_block->i_buffer,
                                p_sys->chans_to_reorder,
                                p_sys->chan_table,
-                               32);
+                               VLC_CODEC_FL32);
         }
 
         /* Render audio into buffer */
index ae15bed277620b70e22bb8abeba0efeda5cec97c..bcf14e74447b1d3d93f87ac42253bf616c6ea3a0 100644 (file)
@@ -86,8 +86,7 @@ struct aout_sys_t
     uint8_t  chans_to_reorder;              /* do we need channel reordering */
     uint8_t  chan_table[AOUT_CHAN_MAX];
     uint32_t i_channel_mask;
-    uint32_t i_bits_per_sample;
-    uint32_t i_channels;
+    vlc_fourcc_t format;
 };
 
 /*****************************************************************************
@@ -724,8 +723,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
     waveformat.Format.nAvgBytesPerSec =
         waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
 
-    p_aout->sys->i_bits_per_sample = waveformat.Format.wBitsPerSample;
-    p_aout->sys->i_channels = i_nb_channels;
+    p_aout->sys->format = i_format;
 
     /* Then fill in the direct sound descriptor */
     memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
@@ -903,7 +901,7 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
             /* Do the channel reordering here */
             aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
                                  p_sys->chans_to_reorder, p_sys->chan_table,
-                                 p_sys->i_bits_per_sample );
+                                 p_sys->format );
 
         memcpy( p_write_position, p_buffer->p_buffer, l_bytes1 );
         block_Release( p_buffer );
index 5a32cca01a72ab744331bc036d4e61ddc23581f2..6d715f59e903b111d4483d0a5509910fcdb2e788 100644 (file)
@@ -71,7 +71,7 @@ typedef struct aout_stream_sys
     uint8_t chans_table[AOUT_CHAN_MAX];
     uint8_t chans_to_reorder;
 
-    uint8_t bits; /**< Bits per sample */
+    vlc_fourcc_t format; /**< Sample format */
     unsigned rate; /**< Sample rate */
     unsigned bytes_per_frame;
     UINT32 written; /**< Frames written to the buffer */
@@ -125,7 +125,7 @@ static HRESULT Play(aout_stream_t *s, block_t *block)
 
     if (sys->chans_to_reorder)
         aout_ChannelReorder(block->p_buffer, block->i_buffer,
-                          sys->chans_to_reorder, sys->chans_table, sys->bits);
+                          sys->chans_to_reorder, sys->chans_table, sys->format);
 
     hr = IAudioClient_GetService(sys->client, &IID_IAudioRenderClient, &pv);
     if (FAILED(hr))
@@ -356,7 +356,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt,
 
     sys->chans_to_reorder = vlc_CheckWaveOrder((hr == S_OK) ? &wf.Format : pwf,
                                                sys->chans_table);
-    sys->bits = fmt->i_bitspersample;
+    sys->format = fmt->i_format;
 
     hr = IAudioClient_Initialize(sys->client, AUDCLNT_SHAREMODE_SHARED, 0,
                                  AOUT_MAX_PREPARE_TIME * 10, 0,
index 8c9b79df44444c0deb9f1ca32cc6b554709a2641..a29f86984c05876a6b477686af47e7deae6cdc1c 100644 (file)
@@ -112,6 +112,7 @@ struct aout_sys_t
 
     uint8_t chans_to_reorder;              /* do we need channel reordering */
     uint8_t chan_table[AOUT_CHAN_MAX];
+    vlc_fourcc_t format;
 };
 
 #include "volume.h"
@@ -654,6 +655,7 @@ static int OpenWaveOut( audio_output_t *p_aout, uint32_t i_device_id, int i_form
                                   p_aout->sys->chan_table );
     if( p_aout->sys->chans_to_reorder )
         msg_Dbg( p_aout, "channel reordering needed" );
+    p_aout->sys->format = i_format;
 
     return VLC_SUCCESS;
 
@@ -917,8 +919,7 @@ static void* WaveOutThread( void *data )
                     aout_ChannelReorder( p_buffer->p_buffer,
                         p_buffer->i_buffer,
                         p_sys->waveformat.Format.nChannels,
-                        p_sys->chan_table,
-                        p_sys->waveformat.Format.wBitsPerSample );
+                        p_sys->chan_table, p_sys->format );
                 }
 
                 PlayWaveOut( p_aout, p_sys->h_waveout,
index b80955ea615029638c5d3f464c2e8abcda8bec77..3ea18c2981c2cb0f7555ac6f1e251028e47f3266 100644 (file)
@@ -430,8 +430,7 @@ static int Demux( demux_t *p_demux )
     if( p_sys->i_chans_to_reorder )
         aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
                              p_sys->fmt.audio.i_channels,
-                             p_sys->pi_chan_table,
-                             p_sys->fmt.audio.i_bitspersample );
+                             p_sys->pi_chan_table, p_sys->fmt.i_codec );
 
     es_out_Send( p_demux->out, p_sys->p_es, p_block );
 
index c1fd87df974dac93f6282e0dfcdfed842245a533..a73428308ecb6bf5b5f17154cec9c5fc6df61226 100644 (file)
@@ -293,8 +293,7 @@ static int Mux( sout_mux_t *p_mux )
         if( p_sys->i_chans_to_reorder )
             aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
                                  p_sys->i_chans_to_reorder,
-                                 p_sys->pi_chan_table,
-                                 p_input->p_fmt->audio.i_bitspersample );
+                                 p_sys->pi_chan_table, p_input->p_fmt->i_codec );
 
         sout_AccessOutWrite( p_mux->p_access, p_block );
     }
index 7552a2df3ec0282329f8c95e33e4c133dbcef70c..93b6a0dd95b862f82c20d0dcbf605ad50c932c4e 100644 (file)
@@ -276,68 +276,130 @@ unsigned aout_CheckChannelReorder( const uint32_t *chans_in,
     return 0;
 }
 
-/*****************************************************************************
- * aout_ChannelReorder :
- *****************************************************************************/
+/**
+ * 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 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,
-                          const uint8_t *chans_table, unsigned bits_per_sample )
+                          const uint8_t *restrict chans_table, vlc_fourcc_t fourcc )
 {
-    size_t samples = bytes / (channels * (bits_per_sample >> 3));
-
+    assert( channels != 0 );
     assert( channels <= AOUT_CHAN_MAX );
 
-    switch( bits_per_sample )
+    /* 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 )
     {
-        case 32:
+        case VLC_CODEC_FL32:
         {
-            uint32_t *buf = ptr;
+            const size_t frames = (bytes / 4) / channels;
+            float *buf = ptr;
 
-            for( size_t i = 0; i < samples; i++ )
+            for( size_t i = 0; i < frames; i++ )
             {
-                uint32_t tmp[AOUT_CHAN_MAX];
+                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 16:
+        case VLC_CODEC_S16N:
         {
-            uint16_t *buf = ptr;
+            const size_t frames = (bytes / 2) / channels;
+            int16_t *buf = ptr;
 
-            for( size_t i = 0; i < samples; i++ )
+            for( size_t i = 0; i < frames; i++ )
             {
-                uint16_t tmp[AOUT_CHAN_MAX];
+                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 8:
+        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];
+
+                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_U8:
         {
+            const size_t frames = bytes / channels;
             uint8_t *buf = ptr;
 
-            for( size_t i = 0; i < samples; i++ )
+            for( size_t i = 0; i < frames; i++ )
             {
                 uint8_t tmp[AOUT_CHAN_MAX];
 
                 for( size_t j = 0; j < channels; j++ )
                     tmp[chans_table[j]] = buf[j];
-
                 memcpy( buf, tmp, channels );
                 buf += channels;
             }
             break;
         }
+
+        default:
+        {
+            unsigned size = aout_BitsPerSample( fourcc ) / 8;
+            const size_t frames = bytes / size;
+            unsigned char *buf = ptr;
+
+            assert( bytes != 0 );
+            for( size_t i = 0; i < frames; i++ )
+            {
+                unsigned char tmp[AOUT_CHAN_MAX * bytes];
+
+                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;
+        }
     }
 }