[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