#include <vlc_common.h>
#include <vlc_aout.h>
#include "aout_internal.h"
+#include "libvlc.h"
/*
* Instances management (internal and external)
{
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('s','3','2','l'):
- case VLC_FOURCC('s','3','2','b'):
- 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:
{
switch ( p_format->i_physical_channels & AOUT_CHAN_PHYSMASK )
{
+ case AOUT_CHAN_LEFT:
+ case AOUT_CHAN_RIGHT:
case AOUT_CHAN_CENTER:
if ( (p_format->i_original_channels & AOUT_CHAN_CENTER)
|| (p_format->i_original_channels
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)
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:
*****************************************************************************/
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 )
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++ )
{
}
}
}
+
+/*****************************************************************************
+ * 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;
+}