[vlc-commits] codec: flac: support non std channel mapping (fix #15005)
Francois Cartegnie
git at videolan.org
Wed Mar 1 17:32:29 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Wed Mar 1 13:22:27 2017 +0100| [705a3603daf2814c9c2cd57933fc42daaa02091d] | committer: Francois Cartegnie
codec: flac: support non std channel mapping (fix #15005)
Assuming the demuxer sends the required extradata (mkv does)
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=705a3603daf2814c9c2cd57933fc42daaa02091d
---
modules/codec/flac.c | 139 +++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 117 insertions(+), 22 deletions(-)
diff --git a/modules/codec/flac.c b/modules/codec/flac.c
index 96adace..661e5d6 100644
--- a/modules/codec/flac.c
+++ b/modules/codec/flac.c
@@ -36,6 +36,8 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_codec.h>
+#include <vlc_codecs.h>
+#include <vlc_aout.h>
#ifdef _WIN32
# define FLAC__NO_DLL
@@ -109,6 +111,35 @@ static const uint8_t ppi_reorder[1+FLAC_MAX_CHANNELS][FLAC_MAX_CHANNELS] =
{ 0, 1, 6, 7, 4, 5, 2, 3 },
};
+/* Flac uses same order as waveformatex */
+#define MAPPED_WFX_CHANNELS 9
+static const uint32_t wfx_remapping[MAPPED_WFX_CHANNELS][2] =
+{
+ { WAVE_SPEAKER_FRONT_LEFT, AOUT_CHAN_LEFT },
+ { WAVE_SPEAKER_FRONT_RIGHT, AOUT_CHAN_RIGHT },
+ { WAVE_SPEAKER_FRONT_CENTER, AOUT_CHAN_CENTER },
+ { WAVE_SPEAKER_LOW_FREQUENCY, AOUT_CHAN_LFE },
+ { WAVE_SPEAKER_BACK_LEFT, AOUT_CHAN_REARLEFT },
+ { WAVE_SPEAKER_BACK_RIGHT, AOUT_CHAN_REARRIGHT },
+ { WAVE_SPEAKER_BACK_CENTER, AOUT_CHAN_REARCENTER },
+ { WAVE_SPEAKER_SIDE_LEFT, AOUT_CHAN_MIDDLELEFT },
+ { WAVE_SPEAKER_SIDE_RIGHT, AOUT_CHAN_MIDDLERIGHT },
+};
+
+static const uint32_t wfx_chans_order[MAPPED_WFX_CHANNELS + 1] =
+{
+ AOUT_CHAN_LEFT,
+ AOUT_CHAN_RIGHT,
+ AOUT_CHAN_CENTER,
+ AOUT_CHAN_LFE,
+ AOUT_CHAN_REARLEFT,
+ AOUT_CHAN_REARRIGHT,
+ AOUT_CHAN_REARCENTER,
+ AOUT_CHAN_MIDDLELEFT,
+ AOUT_CHAN_MIDDLERIGHT,
+ 0
+};
+
/*****************************************************************************
* Local prototypes
*****************************************************************************/
@@ -244,31 +275,91 @@ static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,
decoder_t *p_dec = (decoder_t *)client_data;
decoder_sys_t *p_sys = p_dec->p_sys;
- /* Setup the format */
- p_dec->fmt_out.audio.i_rate = metadata->data.stream_info.sample_rate;
- p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;
- if( metadata->data.stream_info.channels < 9 )
+ switch(metadata->type)
{
- p_dec->fmt_out.audio.i_physical_channels =
- p_dec->fmt_out.audio.i_original_channels =
- pi_channels_maps[metadata->data.stream_info.channels];
- memcpy( p_sys->rgi_channels_reorder,
- ppi_reorder[metadata->data.stream_info.channels],
- metadata->data.stream_info.channels );
- }
- if (!p_dec->fmt_out.audio.i_bitspersample)
- p_dec->fmt_out.audio.i_bitspersample =
- metadata->data.stream_info.bits_per_sample;
-
- msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
- p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
- p_dec->fmt_out.audio.i_bitspersample );
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ /* Setup the format */
+ p_dec->fmt_out.audio.i_rate = metadata->data.stream_info.sample_rate;
+ p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;
+ if( metadata->data.stream_info.channels < 9 )
+ {
+ p_dec->fmt_out.audio.i_physical_channels =
+ p_dec->fmt_out.audio.i_original_channels =
+ pi_channels_maps[metadata->data.stream_info.channels];
+ memcpy( p_sys->rgi_channels_reorder,
+ ppi_reorder[metadata->data.stream_info.channels],
+ metadata->data.stream_info.channels );
+ }
+ if (!p_dec->fmt_out.audio.i_bitspersample)
+ p_dec->fmt_out.audio.i_bitspersample =
+ metadata->data.stream_info.bits_per_sample;
+
+ msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",
+ p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,
+ p_dec->fmt_out.audio.i_bitspersample );
+
+ p_sys->b_stream_info = true;
+ p_sys->stream_info = metadata->data.stream_info;
+
+ date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
+ date_Set( &p_sys->end_date, VLC_TS_INVALID );
+ break;
- p_sys->b_stream_info = true;
- p_sys->stream_info = metadata->data.stream_info;
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ for( FLAC__uint32 i=0; i<metadata->data.vorbis_comment.num_comments; i++ )
+ {
+ const FLAC__StreamMetadata_VorbisComment_Entry *comment =
+ &metadata->data.vorbis_comment.comments[i];
+ /* Check for custom WAVEFORMATEX channel ordering */
+ if( comment->length > 34 &&
+ !strncmp( "WAVEFORMATEXTENSIBLE_CHANNEL_MASK=", (char *) comment->entry, 34 ) )
+ {
+ char *endptr = (char *) &comment->entry[34] + comment->length;
+ const uint32_t i_wfxmask = strtoul( (char *) &comment->entry[34], &endptr, 16 );
+ const unsigned i_wfxchannels = popcount( i_wfxmask );
+ if( i_wfxchannels > 0 && i_wfxchannels <= AOUT_CHAN_MAX )
+ {
+ /* Create the vlc bitmap from wfx channels */
+ uint32_t i_vlcmask = 0;
+ for( uint32_t i_chan = 1; i_chan && i_chan <= i_wfxmask; i_chan <<= 1 )
+ {
+ if( (i_chan & i_wfxmask) == 0 )
+ continue;
+ for( size_t i=0; i<MAPPED_WFX_CHANNELS; i++ )
+ {
+ if( wfx_remapping[i][0] == i_chan )
+ i_vlcmask |= wfx_remapping[i][1];
+ }
+ }
+ /* Check if we have the 1 to 1 mapping */
+ if( popcount(i_vlcmask) != i_wfxchannels )
+ {
+ msg_Warn( p_dec, "Unsupported channel mask %x", i_wfxmask );
+ return;
+ }
+
+ /* Compute the remapping */
+ uint8_t neworder[AOUT_CHAN_MAX] = {0};
+ aout_CheckChannelReorder( wfx_chans_order, NULL,
+ i_vlcmask, neworder );
+
+ /* /!\ Invert our source/dest reordering,
+ * as Interleave() here works source indexes */
+ for( unsigned i=0; i<i_wfxchannels; i++ )
+ p_sys->rgi_channels_reorder[neworder[i]] = i;
+
+ p_dec->fmt_out.audio.i_physical_channels =
+ p_dec->fmt_out.audio.i_original_channels = i_vlcmask;
+ p_dec->fmt_out.audio.i_channels = i_wfxchannels;
+ }
+
+ break;
+ }
+ }
- date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
- date_Set( &p_sys->end_date, VLC_TS_INVALID );
+ default:
+ break;
+ }
}
/*****************************************************************************
@@ -335,6 +426,10 @@ static int OpenDecoder( vlc_object_t *p_this )
return VLC_EGENERIC;
}
+ /* Enable STREAMINFO + COMMENTS */
+ FLAC__stream_decoder_set_metadata_respond( p_sys->p_flac,
+ FLAC__METADATA_TYPE_VORBIS_COMMENT );
+
#ifdef USE_NEW_FLAC_API
if( FLAC__stream_decoder_init_stream( p_sys->p_flac,
DecoderReadCallback,
More information about the vlc-commits
mailing list