Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
dd71c902 by Steve Lhomme at 2026-01-22T11:28:17+01:00
demux: mkv: fix string to chapter_uid conversion

The integer can use the whole uint64_t range.
std::stoul() will generate a std::out_of_range exception on values larger than 
a uint32_t.

Ref. #29553

- - - - -
ccc17742 by Steve Lhomme at 2026-01-22T11:28:17+01:00
demux: mkv: pass the MatroskaChapterProcessTime to the command interpreter

We may want to know when the chapter is entering/leaving with the command.

- - - - -
e32aac78 by Steve Lhomme at 2026-01-22T11:28:17+01:00
demux: mkv: avoid infinite loop on entering a chapter with GotoAndPlay(<itself>)

- - - - -
b63629f2 by Steve Lhomme at 2026-01-22T11:28:17+01:00
demux: mkv: discard GotoAndPlay command if there's extra text before the 
parenthesis

- GotoAndPlay() is supported
- GotoAndPlay   () is supported
- GotoAndPlay abc() is not supported

Ref. #29553

- - - - -
e2c579c7 by Steve Lhomme at 2026-01-22T11:28:17+01:00
demux: mkv: only interpret the command has a value to interpret

- - - - -


8 changed files:

- modules/demux/mkv/chapter_command.cpp
- modules/demux/mkv/chapter_command.hpp
- modules/demux/mkv/chapter_command_dvd.cpp
- modules/demux/mkv/chapter_command_dvd.hpp
- modules/demux/mkv/chapter_command_script.cpp
- modules/demux/mkv/chapter_command_script.hpp
- modules/demux/mkv/chapter_command_script_common.cpp
- modules/demux/mkv/chapter_command_script_common.hpp


Changes:

=====================================
modules/demux/mkv/chapter_command.cpp
=====================================
@@ -25,14 +25,6 @@
 
 #include <vlc_arrays.h>
 
-#if LIBMATROSKA_VERSION < 0x010700
-typedef enum {
-  MATROSKA_CHAPPROCESSTIME_DURING           = 0,
-  MATROSKA_CHAPPROCESSTIME_BEFORE           = 1,
-  MATROSKA_CHAPPROCESSTIME_AFTER            = 2,
-} MatroskaChapterProcessTime;
-#endif
-
 namespace mkv {
 
 void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & 
command )


=====================================
modules/demux/mkv/chapter_command.hpp
=====================================
@@ -30,6 +30,15 @@
 
 struct vlc_spu_highlight_t;
 
+#if LIBMATROSKA_VERSION < 0x010700
+typedef enum {
+  MATROSKA_CHAPPROCESSTIME_DURING           = 0,
+  MATROSKA_CHAPPROCESSTIME_BEFORE           = 1,
+  MATROSKA_CHAPPROCESSTIME_AFTER            = 2,
+} MatroskaChapterProcessTime;
+#endif
+
+
 namespace mkv {
 
 class virtual_chapter_c;


=====================================
modules/demux/mkv/chapter_command_dvd.cpp
=====================================
@@ -36,15 +36,15 @@ int16_t dvd_chapter_codec_c::GetTitleNumber() const
 
 bool dvd_chapter_codec_c::Enter()
 {
-    return EnterLeaveHelper( "Matroska DVD enter command", enter_cmds );
+    return EnterLeaveHelper( "Matroska DVD enter command", enter_cmds, 
MATROSKA_CHAPPROCESSTIME_BEFORE );
 }
 
 bool dvd_chapter_codec_c::Leave()
 {
-    return EnterLeaveHelper( "Matroska DVD leave command", leave_cmds );
+    return EnterLeaveHelper( "Matroska DVD leave command", leave_cmds, 
MATROSKA_CHAPPROCESSTIME_AFTER );
 }
 
-bool dvd_chapter_codec_c::EnterLeaveHelper( char const * str_diag, 
ChapterProcess & p_container )
+bool dvd_chapter_codec_c::EnterLeaveHelper( char const * str_diag, 
ChapterProcess & p_container, MatroskaChapterProcessTime process_time )
 {
     bool f_result = false;
     ChapterProcess::iterator it = p_container.begin ();
@@ -57,7 +57,7 @@ bool dvd_chapter_codec_c::EnterLeaveHelper( char const * 
str_diag, ChapterProces
             for( ; i_size > 0; i_size -=1, p_data += 8 )
             {
                 vlc_debug( l, "%s", str_diag);
-                f_result |= intepretor.Interpret( p_data );
+                f_result |= intepretor.Interpret( process_time, p_data, 8 );
             }
         }
         ++it;
@@ -108,7 +108,7 @@ std::string dvd_chapter_codec_c::GetCodecName( bool 
f_for_title ) const
 }
 
 // see http://www.dvd-replica.com/DVD/vmcmdset.php for a description of DVD 
commands
-bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t 
i_size )
+bool dvd_command_interpretor_c::Interpret( MatroskaChapterProcessTime, const 
binary * p_command, size_t i_size )
 {
     if ( i_size != 8 )
         return false;
@@ -582,7 +582,7 @@ bool dvd_command_interpretor_c::ProcessNavAction( uint16_t 
button )
     if ( button_ptr.auto_action_mode )
     {
         // process the button action
-        return Interpret( button_ptr.cmd.bytes, 8 );
+        return Interpret( MATROSKA_CHAPPROCESSTIME_DURING, 
button_ptr.cmd.bytes, 8 );
     }
     return false;
 }
@@ -605,7 +605,7 @@ bool dvd_command_interpretor_c::HandleKeyEvent( 
NavivationKey key )
     case DOWN:  return ProcessNavAction( button_ptr.down );
     case OK:
         // process the button action
-        return Interpret( button_ptr.cmd.bytes, 8 );
+        return Interpret( MATROSKA_CHAPPROCESSTIME_DURING, 
button_ptr.cmd.bytes, 8 );
     case MENU:
     case POPUP:
         return false;
@@ -657,7 +657,7 @@ void dvd_command_interpretor_c::HandleMousePressed( 
unsigned x, unsigned y )
 
     // process the button action
     SetSPRM( 0x88, best );
-    Interpret( button_ptr.cmd.bytes, 8 );
+    Interpret( MATROSKA_CHAPPROCESSTIME_DURING, button_ptr.cmd.bytes, 8 );
 
     vlc_debug( l, "Processed button %d", best );
 


=====================================
modules/demux/mkv/chapter_command_dvd.hpp
=====================================
@@ -33,7 +33,7 @@ public:
         p_PRMs[ 0x80 + 18 ] = 0xFFFFu;
     }
 
-    bool Interpret( const binary * p_command, size_t i_size = 8 );
+    bool Interpret( MatroskaChapterProcessTime, const binary * p_command, 
size_t i_size );
 
     bool HandleKeyEvent( NavivationKey );
     void HandleMousePressed( unsigned x, unsigned y );
@@ -201,7 +201,7 @@ public:
     int16_t GetTitleNumber() const override;
 
 protected:
-    bool EnterLeaveHelper( char const*, ChapterProcess & );
+    bool EnterLeaveHelper( char const*, ChapterProcess &, 
MatroskaChapterProcessTime );
     dvd_command_interpretor_c & intepretor;
 };
 


=====================================
modules/demux/mkv/chapter_command_script.cpp
=====================================
@@ -16,7 +16,7 @@ const std::string 
matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAnd
 
 // see http://www.matroska.org/technical/specs/chapters/index.html#mscript
 //  for a description of existing commands
-bool matroska_script_interpretor_c::Interpret( const binary * p_command, 
size_t i_size )
+bool matroska_script_interpretor_c::Interpret( MatroskaChapterProcessTime 
time, const binary * p_command, size_t i_size )
 {
     bool b_result = false;
 
@@ -31,11 +31,14 @@ bool matroska_script_interpretor_c::Interpret( const binary 
* p_command, size_t
         // find the (
         for ( i=CMD_MS_GOTO_AND_PLAY.size(); i<sz_command.size(); i++)
         {
+            if ( sz_command[i] == ' ' )
+                continue;
             if ( sz_command[i] == '(' )
             {
                 i++;
                 break;
             }
+            return false; // extra characters between command and ( is not 
supported
         }
         // find the )
         for ( j=i; j<sz_command.size(); j++)
@@ -47,19 +50,29 @@ bool matroska_script_interpretor_c::Interpret( const binary 
* p_command, size_t
             }
         }
 
-        std::string st = sz_command.substr( i+1, j-i-1 );
-        chapter_uid i_chapter_uid = std::stoul( st );
+        if(i+1 < j-i-1)
+        {
+            std::string st = sz_command.substr( i+1, j-i-1 );
+            chapter_uid i_chapter_uid = std::stoull( st );
 
-        virtual_segment_c *p_vsegment;
-        virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, 
p_vsegment );
+            virtual_segment_c *p_vsegment;
+            virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, 
p_vsegment );
 
-        if ( p_vchapter == NULL )
-            vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid);
-        else
-        {
-            if ( !p_vchapter->EnterAndLeave( 
vm.GetCurrentVSegment()->CurrentChapter(), false ) )
-                vm.JumpTo( *p_vsegment, *p_vchapter );
-            b_result = true;
+            if ( p_vchapter == NULL )
+                vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid);
+            else
+            {
+                auto current_chapter = 
vm.GetCurrentVSegment()->CurrentChapter();
+                if ( p_vchapter == current_chapter) {
+                    if ( time == MATROSKA_CHAPPROCESSTIME_BEFORE )
+                        // the enter command is enter itself, avoid infinite 
loop
+                        return false;
+                    vm.JumpTo( *p_vsegment, *p_vchapter );
+                }
+                else if ( !p_vchapter->EnterAndLeave( current_chapter, false ) 
)
+                    vm.JumpTo( *p_vsegment, *p_vchapter );
+                b_result = true;
+            }
         }
     }
 


=====================================
modules/demux/mkv/chapter_command_script.hpp
=====================================
@@ -19,7 +19,7 @@ public:
     :matroska_script_interpreter_common_c(log, vm_)
     {}
 
-    bool Interpret( const binary * p_command, size_t i_size ) override;
+    bool Interpret( MatroskaChapterProcessTime, const binary * p_command, 
size_t i_size ) override;
 
     // Matroska Script commands
     static const std::string CMD_MS_GOTO_AND_PLAY;


=====================================
modules/demux/mkv/chapter_command_script_common.cpp
=====================================
@@ -1,7 +1,7 @@
 // Copyright (C) 2024 VLC authors and VideoLAN
 // SPDX-License-Identifier: LGPL-2.1-or-later
 //
-// chapter_command_script_common.cpp : 
+// chapter_command_script_common.cpp :
 // Common file for Matroska JS and Matroska Script
 // Authors: Laurent Aimar <[email protected]>
 //          Steve Lhomme <[email protected]>
@@ -21,7 +21,7 @@ bool matroska_script_codec_common_c::Enter()
         if ( (*index).GetSize() )
         {
             vlc_debug( l, "Matroska Script enter command" );
-            f_result |= get_interpreter().Interpret( (*index).GetBuffer(), 
(*index).GetSize() );
+            f_result |= get_interpreter().Interpret( 
MATROSKA_CHAPPROCESSTIME_BEFORE, (*index).GetBuffer(), (*index).GetSize() );
         }
         ++index;
     }
@@ -37,7 +37,7 @@ bool matroska_script_codec_common_c::Leave()
         if ( (*index).GetSize() )
         {
             vlc_debug( l, "Matroska Script leave command" );
-            f_result |= get_interpreter().Interpret( (*index).GetBuffer(), 
(*index).GetSize() );
+            f_result |= get_interpreter().Interpret( 
MATROSKA_CHAPPROCESSTIME_AFTER, (*index).GetBuffer(), (*index).GetSize() );
         }
         ++index;
     }


=====================================
modules/demux/mkv/chapter_command_script_common.hpp
=====================================
@@ -23,7 +23,7 @@ public:
     virtual ~matroska_script_interpreter_common_c() = default;
 
     // DVD command IDs
-    virtual bool Interpret( const binary * p_command, size_t i_size ) = 0;
+    virtual bool Interpret( MatroskaChapterProcessTime time, const binary * 
p_command, size_t i_size ) = 0;
 
 protected:
     struct vlc_logger *l;



View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/f4b7c133c5752e958912181e6a1e22b875417e87...e2c579c7dfc5ca69913357bc086cbbae1031dbec

-- 
View it on GitLab: 
https://code.videolan.org/videolan/vlc/-/compare/f4b7c133c5752e958912181e6a1e22b875417e87...e2c579c7dfc5ca69913357bc086cbbae1031dbec
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits

Reply via email to