[vlc-commits] [Git][videolan/vlc][master] 2 commits: demux: mkv: improve wav multichannel support
Steve Lhomme (@robUx4)
gitlab at videolan.org
Thu Aug 6 13:45:53 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
cd41b6e0 by Steve Lhomme at 2026-08-06T13:04:59+00:00
demux: mkv: improve wav multichannel support
Similar to the wav.c ChunkParseFmt() code from 93387674915f623381cd08aedb0638b238c19104.
Fixes #29969
- - - - -
ce7c6777 by Steve Lhomme at 2026-08-06T13:04:59+00:00
demux: mkv: avoid casting to WAVEFORMATEX
- - - - -
1 changed file:
- modules/demux/mkv/matroska_segment_parse.cpp
Changes:
=====================================
modules/demux/mkv/matroska_segment_parse.cpp
=====================================
@@ -1938,7 +1938,7 @@ bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
mkv_track_t * p_tk = vars.p_tk;
es_format_t * p_fmt = &vars.p_tk->fmt;
- if( p_tk->i_extra_data < (int)sizeof( WAVEFORMATEX ) )
+ if( p_tk->i_extra_data < sizeof( WAVEFORMATEX ) )
{
msg_Err( vars.p_demuxer, "missing/invalid WAVEFORMATEX" );
p_tk->fmt.i_codec = VLC_CODEC_UNKNOWN;
@@ -1946,31 +1946,31 @@ bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
else
{
ONLY_FMT(AUDIO);
- WAVEFORMATEX *p_wf = (WAVEFORMATEX*)p_tk->p_extra_data;
- p_tk->fmt.audio.i_channels = GetWLE( &p_wf->nChannels );
- p_tk->fmt.audio.i_rate = GetDWLE( &p_wf->nSamplesPerSec );
- p_tk->fmt.i_bitrate = GetDWLE( &p_wf->nAvgBytesPerSec ) * 8;
- p_tk->fmt.audio.i_blockalign = GetWLE( &p_wf->nBlockAlign );
- p_tk->fmt.audio.i_bitspersample = GetWLE( &p_wf->wBitsPerSample );
+ p_tk->fmt.audio.i_channels = GetWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, nChannels) );
+ p_tk->fmt.audio.i_rate = GetDWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, nSamplesPerSec) );
+ p_tk->fmt.i_bitrate = GetDWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, nAvgBytesPerSec) ) * 8;
+ p_tk->fmt.audio.i_blockalign = GetWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, nBlockAlign) );
+ p_tk->fmt.audio.i_bitspersample = GetWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, wBitsPerSample) );
- p_tk->fmt.i_extra = GetWLE( &p_wf->cbSize );
- if ( (size_t)p_tk->fmt.i_extra > p_tk->i_extra_data - sizeof( WAVEFORMATEX ) )
+ p_tk->fmt.i_extra = GetWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, cbSize) );
+ if ( p_tk->fmt.i_extra > p_tk->i_extra_data - sizeof( WAVEFORMATEX ) )
p_tk->fmt.i_extra = 0;
if( p_tk->fmt.i_extra != 0 )
{
p_tk->fmt.p_extra = xmalloc( p_tk->fmt.i_extra );
if( p_tk->fmt.p_extra )
- memcpy( p_tk->fmt.p_extra, &p_wf[1], p_tk->fmt.i_extra );
+ memcpy( p_tk->fmt.p_extra, p_tk->p_extra_data + sizeof(WAVEFORMATEX), p_tk->fmt.i_extra );
else
p_tk->fmt.i_extra = 0;
}
- if( p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ uint16_t wFormatTag = GetWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEX, wFormatTag) );
+ if( wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
p_tk->i_extra_data >= sizeof(WAVEFORMATEXTENSIBLE) )
{
- WAVEFORMATEXTENSIBLE *p_wext = container_of(p_wf, WAVEFORMATEXTENSIBLE, Format);
- GUID subFormat = p_wext->SubFormat;
+ GUID subFormat;
+ memcpy(&subFormat, p_tk->p_extra_data + offsetof(WAVEFORMATEXTENSIBLE, SubFormat), sizeof(GUID) );
sf_tag_to_fourcc( &subFormat, &p_tk->fmt.i_codec, NULL);
/* FIXME should we use Samples */
@@ -1978,11 +1978,46 @@ bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
if( p_tk->fmt.audio.i_channels > 2 &&
( p_tk->fmt.i_codec != VLC_CODEC_UNKNOWN ) )
{
- uint32_t wfextcm = GetDWLE( &p_wext->dwChannelMask );
+ uint32_t wfextcm = GetDWLE( p_tk->p_extra_data + offsetof(WAVEFORMATEXTENSIBLE, dwChannelMask) );
int match;
unsigned i_channel_mask = getChannelMask( &wfextcm,
p_tk->fmt.audio.i_channels,
&match );
+
+ if( match < p_fmt->audio.i_channels )
+ {
+ int i_missing = p_fmt->audio.i_channels - match;
+ msg_Warn( vars.p_demuxer, "Trying to fill up unspecified position for %d channels", p_fmt->audio.i_channels - match );
+
+ static const uint32_t pi_pair[] = { AOUT_CHAN_REARLEFT|AOUT_CHAN_REARRIGHT,
+ AOUT_CHAN_MIDDLELEFT|AOUT_CHAN_MIDDLERIGHT,
+ AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT };
+
+ /* Try to complete with pair */
+ for( unsigned i = 0; i < ARRAY_SIZE(pi_pair); i++ )
+ {
+ if( i_missing >= 2 && !(i_channel_mask & pi_pair[i] ) )
+ {
+ i_missing -= 2;
+ i_channel_mask |= pi_pair[i];
+ }
+ }
+ /* Well fill up with what we can */
+ for( unsigned i = 0; i < ARRAY_SIZE(pi_channels_aout) && i_missing > 0; i++ )
+ {
+ if( !( i_channel_mask & pi_channels_aout[i] ) )
+ {
+ i_channel_mask |= pi_channels_aout[i];
+ i_missing--;
+
+ if( i_missing <= 0 )
+ break;
+ }
+ }
+
+ match = p_fmt->audio.i_channels - i_missing;
+ }
+
p_tk->fmt.i_codec = vlc_fourcc_GetCodecAudio( p_tk->fmt.i_codec,
p_tk->fmt.audio.i_bitspersample );
if( i_channel_mask )
@@ -1998,19 +2033,19 @@ bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
}
else
{
- wf_tag_to_fourcc( GetWLE( &p_wf->wFormatTag ), &p_tk->fmt.i_codec, NULL );
- if( p_wf->wFormatTag == WAVE_FORMAT_AAC_LATM )
+ wf_tag_to_fourcc( wFormatTag, &p_tk->fmt.i_codec, NULL );
+ if( wFormatTag == WAVE_FORMAT_AAC_LATM )
{
p_tk->fmt.i_original_fourcc = VLC_FOURCC('L','A','T','M');
}
- else if( p_wf->wFormatTag == WAVE_FORMAT_AAC_ADTS )
+ else if( wFormatTag == WAVE_FORMAT_AAC_ADTS )
{
p_tk->fmt.i_original_fourcc = VLC_FOURCC('A','D','T','S');
}
}
if( p_tk->fmt.i_codec == VLC_CODEC_UNKNOWN )
- msg_Err( vars.p_demuxer, "Unrecognized wf tag: 0x%x", GetWLE( &p_wf->wFormatTag ) );
+ msg_Err( vars.p_demuxer, "Unrecognized wf tag: 0x%x", wFormatTag );
}
p_fmt->b_packetized = !p_fmt->audio.i_blockalign;
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6e6ad1654b6263c467a6e7c0795a9493754afbd2...ce7c67776dff8a469a4aa7b5f9eb54702b4cdc21
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6e6ad1654b6263c467a6e7c0795a9493754afbd2...ce7c67776dff8a469a4aa7b5f9eb54702b4cdc21
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list