[vlc-commits] [Git][videolan/vlc][master] 30 commits: demux: mkv: keep the DVD interpretor in each DVD chapter codec instance

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Jul 7 12:29:43 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
072f7ca2 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: keep the DVD interpretor in each DVD chapter codec instance

- - - - -
0100ddd1 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: don't use the DVD interpretor if it's not usable

- - - - -
dc94e118 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: add a generic interface between the Chapter Codec and the demuxer

- - - - -
24b55eb8 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use a logger object to log Chapter Codec commands

- - - - -
c41b59e6 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use C++ lamba with BrowseCodecPrivate

So we can pass the proper type directly to each call.

- - - - -
eeeec6d0 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: make MATROSKA_DVD_LEVEL_xxx private

- - - - -
6c69a7ba by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use a specific type for Chapter UIDs

- - - - -
1665c95a by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: initialize chapter values directly

- - - - -
f1732719 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: make the chapter end time optional

It's only mandatory for ordered chapters.

- - - - -
f6beea41 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: forbid ordered chapters without an end time

Otherwise it's not spec-compliant.

- - - - -
05f992ed by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: only use the chapter end time if it's >= start time

Otherwise it's not spec-compliant.

- - - - -
a026a92c by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: initialize the current virtual_segment chapter internally

- - - - -
884f1b55 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: make the virtual_segment current chapter private

- - - - -
4383e74b by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: add missing override in dvd_chapter_codec_c

- - - - -
976ea3e9 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: make chapter_codec_cmds_c::GetTitleNumber() const

- - - - -
590b780e by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use range based loops to navigate chapter codecs

Co-authored-by: Alaric Senat <alaric at videolabs.io>

- - - - -
68db925c by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use const for internal KeepTrackSelection

- - - - -
e49f3b06 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use more const in loops

- - - - -
c73b49bf by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: turn FindSegment() into SegmentIsOpened()

We don't need to have the actual Segment.

- - - - -
7d4f01a3 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: rename segments to opened_segments

It's really the list of opened/known Matroska Segments.

- - - - -
546e3014 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: create a vitual chapter edition with a const list of opened segments

- - - - -
298c59f4 by Steve Lhomme at 2024-07-07T12:12:56+00:00
Revert "demux: mkv: fix seek segfault with invalid chapters"

This reverts commit 4ba01f2831193b2a59513c897b159c14c0a9f086.

Let p_vsegment->Seek() decide what is valid or not.
The p_segment is actually the p_vsegment's current chapter's actual segment.
The current chapter segment may be NULL, but that doesn't mean we can't seek.
The current chapter segment cannot be NULL, per its constructor.

- - - - -
c60f5f92 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: return early in virtual_segment_c::Seek()

And simplify indentation.

- - - - -
7ba9f8c4 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: move the seeking out of PreparePlayback()

No functional changes.

- - - - -
44c98eca by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: only use the new virtual segment if it has a segment

The inifial virtual segment is already checked for that.

- - - - -
57424c9b by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: make the current virtual segment private

- - - - -
e2d8135a by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: remove always NULL virtual chapter seek parameter

- - - - -
1590c3e8 by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: fallthrough to the regular seek

No need for a recursive call, we'll get the same values from the same chapter.

And if the Seek fails, we should know.

- - - - -
4b3bc54f by Alexandre Janniaux at 2024-07-07T12:12:56+00:00
demux: mkv: only check once the interpreter is available

- - - - -
0479c4ab by Steve Lhomme at 2024-07-07T12:12:56+00:00
demux: mkv: use more const and less pointers

- - - - -


15 changed files:

- modules/demux/mkv/chapter_command.cpp
- modules/demux/mkv/chapter_command.hpp
- modules/demux/mkv/chapters.cpp
- modules/demux/mkv/chapters.hpp
- modules/demux/mkv/demux.cpp
- modules/demux/mkv/demux.hpp
- modules/demux/mkv/events.cpp
- modules/demux/mkv/events.hpp
- modules/demux/mkv/matroska_segment.hpp
- modules/demux/mkv/matroska_segment_parse.cpp
- modules/demux/mkv/mkv.cpp
- modules/demux/mkv/mkv.hpp
- modules/demux/mkv/util.cpp
- modules/demux/mkv/virtual_segment.cpp
- modules/demux/mkv/virtual_segment.hpp


Changes:

=====================================
modules/demux/mkv/chapter_command.cpp
=====================================
@@ -27,6 +27,14 @@
 
 namespace mkv {
 
+constexpr binary MATROSKA_DVD_LEVEL_SS   = 0x30;
+constexpr binary MATROSKA_DVD_LEVEL_LU   = 0x2A;
+constexpr binary MATROSKA_DVD_LEVEL_TT   = 0x28;
+constexpr binary MATROSKA_DVD_LEVEL_PGC  = 0x20;
+constexpr binary MATROSKA_DVD_LEVEL_PG   = 0x18;
+constexpr binary MATROSKA_DVD_LEVEL_PTT  = 0x10;
+constexpr binary MATROSKA_DVD_LEVEL_CN   = 0x08;
+
 void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & command )
 {
     uint32_t codec_time = uint32_t(-1);
@@ -55,7 +63,7 @@ void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & command
     }
 }
 
-int16_t dvd_chapter_codec_c::GetTitleNumber()
+int16_t dvd_chapter_codec_c::GetTitleNumber() const
 {
     if ( p_private_data->GetSize() >= 3)
     {
@@ -90,8 +98,8 @@ bool dvd_chapter_codec_c::EnterLeaveHelper( char const * str_diag, std::vector<K
             size_t i_size  = std::min<size_t>( *p_data++, ( (*it)->GetSize() - 1 ) >> 3 ); // avoid reading too much
             for( ; i_size > 0; i_size -=1, p_data += 8 )
             {
-                msg_Dbg( &sys.demuxer, "%s", str_diag);
-                f_result |= sys.GetDVDInterpretor().Interpret( p_data );
+                vlc_debug( l, "%s", str_diag);
+                f_result |= intepretor.Interpret( p_data );
             }
         }
         ++it;
@@ -140,8 +148,6 @@ std::string dvd_chapter_codec_c::GetCodecName( bool f_for_title ) const
 
     return result;
 }
-class virtual_segment_c;
-class chapter_item_c;
 
 // 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 )
@@ -202,7 +208,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
         {
         case CMD_DVD_IF_GPREG_EQUAL:
             // if equals
-            msg_Dbg( &sys.demuxer, "IF %s EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) == i_value ))
             {
                 b_test_positive = false;
@@ -210,7 +216,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_NOT_EQUAL:
             // if not equals
-            msg_Dbg( &sys.demuxer, "IF %s NOT EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s NOT EQUALS %s", GetRegTypeName( false, i_cr1 ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) != i_value ))
             {
                 b_test_positive = false;
@@ -218,7 +224,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_INF:
             // if inferior
-            msg_Dbg( &sys.demuxer, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) < i_value ))
             {
                 b_test_positive = false;
@@ -226,7 +232,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_INF_EQUAL:
             // if inferior or equal
-            msg_Dbg( &sys.demuxer, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s < %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) <= i_value ))
             {
                 b_test_positive = false;
@@ -234,7 +240,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_AND:
             // if logical and
-            msg_Dbg( &sys.demuxer, "IF %s & %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s & %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) & i_value ))
             {
                 b_test_positive = false;
@@ -242,7 +248,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_SUP:
             // if superior
-            msg_Dbg( &sys.demuxer, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) > i_value ))
             {
                 b_test_positive = false;
@@ -250,7 +256,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             break;
         case CMD_DVD_IF_GPREG_SUP_EQUAL:
             // if superior or equal
-            msg_Dbg( &sys.demuxer, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
+            vlc_debug( l, "IF %s >= %s", GetRegTypeName( false, p_command[3] ).c_str(), GetRegTypeName( b_test_value, i_value ).c_str() );
             if (!( GetPRM( i_cr1 ) >= i_value ))
             {
                 b_test_positive = false;
@@ -270,30 +276,36 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
     case CMD_DVD_NOP:
     case CMD_DVD_NOP2:
         {
-            msg_Dbg( &sys.demuxer, "NOP" );
+            vlc_debug( l, "NOP" );
             break;
         }
     case CMD_DVD_BREAK:
         {
-            msg_Dbg( &sys.demuxer, "Break" );
+            vlc_debug( l, "Break" );
             // TODO
             break;
         }
     case CMD_DVD_JUMP_TT:
         {
             uint8_t i_title = p_command[5];
-            msg_Dbg( &sys.demuxer, "JumpTT %d", i_title );
+            vlc_debug( l, "JumpTT %d", i_title );
 
             // find in the ChapProcessPrivate matching this Title level
-            p_vchapter = sys.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchTitleNumber, &i_title, sizeof(i_title), p_vsegment );
+            p_vchapter = vm.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                [i_title](const chapter_codec_cmds_c &data) {
+                    return MatchTitleNumber(data, i_title);
+                }, p_vsegment );
             if ( p_vsegment != NULL && p_vchapter != NULL )
             {
                 /* enter via the First Cell */
                 uint8_t i_cell = 1;
-                p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchCellNumber, &i_cell, sizeof(i_cell) );
+                p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                    [i_cell](const chapter_codec_cmds_c &data) {
+                        return MatchCellNumber( data, i_cell );
+                    });
                 if ( p_vchapter != NULL )
                 {
-                    sys.JumpTo( *p_vsegment, *p_vchapter );
+                    vm.JumpTo( *p_vsegment, *p_vchapter );
                     f_result = true;
                 }
             }
@@ -302,7 +314,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
         }
     case CMD_DVD_CALLSS_VTSM1:
         {
-            msg_Dbg( &sys.demuxer, "CallSS" );
+            vlc_debug( l, "CallSS" );
             binary p_type;
             switch( (p_command[6] & 0xC0) >> 6 ) {
                 case 0:
@@ -310,97 +322,106 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
                     switch ( p_type )
                     {
                     case 0x00:
-                        msg_Dbg( &sys.demuxer, "CallSS PGC (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS PGC (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x02:
-                        msg_Dbg( &sys.demuxer, "CallSS Title Entry (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Title Entry (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x03:
-                        msg_Dbg( &sys.demuxer, "CallSS Root Menu (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Root Menu (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x04:
-                        msg_Dbg( &sys.demuxer, "CallSS Subpicture Menu (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Subpicture Menu (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x05:
-                        msg_Dbg( &sys.demuxer, "CallSS Audio Menu (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Audio Menu (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x06:
-                        msg_Dbg( &sys.demuxer, "CallSS Angle Menu (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Angle Menu (rsm_cell %x)", p_command[4]);
                         break;
                     case 0x07:
-                        msg_Dbg( &sys.demuxer, "CallSS Chapter Menu (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS Chapter Menu (rsm_cell %x)", p_command[4]);
                         break;
                     default:
-                        msg_Dbg( &sys.demuxer, "CallSS <unknown> (rsm_cell %x)", p_command[4]);
+                        vlc_debug( l, "CallSS <unknown> (rsm_cell %x)", p_command[4]);
                         break;
                     }
-                    p_vchapter = sys.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchPgcType, &p_type, 1, p_vsegment );
+                    p_vchapter = vm.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                        [p_type](const chapter_codec_cmds_c &data) {
+                            return MatchPgcType( data, p_type );
+                        }, p_vsegment );
                     if ( p_vsegment != NULL && p_vchapter != NULL )
                     {
                         /* enter via the first Cell */
                         uint8_t i_cell = 1;
-                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchCellNumber, &i_cell, sizeof(i_cell) );
+                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                            [i_cell](const chapter_codec_cmds_c &data) {
+                                return MatchCellNumber( data, i_cell ); } );
                         if ( p_vchapter != NULL )
                         {
-                            sys.JumpTo( *p_vsegment, *p_vchapter );
+                            vm.JumpTo( *p_vsegment, *p_vchapter );
                             f_result = true;
                         }
                     }
                 break;
                 case 1:
-                    msg_Dbg( &sys.demuxer, "CallSS VMGM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
+                    vlc_debug( l, "CallSS VMGM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
                 break;
                 case 2:
-                    msg_Dbg( &sys.demuxer, "CallSS VTSM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
+                    vlc_debug( l, "CallSS VTSM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
                 break;
                 case 3:
-                    msg_Dbg( &sys.demuxer, "CallSS VMGM (pgc %d, rsm_cell %x)", (p_command[2] << 8) + p_command[3], p_command[4]);
+                    vlc_debug( l, "CallSS VMGM (pgc %d, rsm_cell %x)", (p_command[2] << 8) + p_command[3], p_command[4]);
                 break;
             }
             break;
         }
     case CMD_DVD_JUMP_SS:
         {
-            msg_Dbg( &sys.demuxer, "JumpSS");
+            vlc_debug( l, "JumpSS");
             binary p_type;
             switch( (p_command[5] & 0xC0) >> 6 ) {
                 case 0:
-                    msg_Dbg( &sys.demuxer, "JumpSS FP");
+                    vlc_debug( l, "JumpSS FP");
                 break;
                 case 1:
                     p_type = p_command[5] & 0x0F;
                     switch ( p_type )
                     {
                     case 0x02:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Title Entry");
+                        vlc_debug( l, "JumpSS VMGM Title Entry");
                         break;
                     case 0x03:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Root Menu");
+                        vlc_debug( l, "JumpSS VMGM Root Menu");
                         break;
                     case 0x04:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Subpicture Menu");
+                        vlc_debug( l, "JumpSS VMGM Subpicture Menu");
                         break;
                     case 0x05:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Audio Menu");
+                        vlc_debug( l, "JumpSS VMGM Audio Menu");
                         break;
                     case 0x06:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Angle Menu");
+                        vlc_debug( l, "JumpSS VMGM Angle Menu");
                         break;
                     case 0x07:
-                        msg_Dbg( &sys.demuxer, "JumpSS VMGM Chapter Menu");
+                        vlc_debug( l, "JumpSS VMGM Chapter Menu");
                         break;
                     default:
-                        msg_Dbg( &sys.demuxer, "JumpSS <unknown>");
+                        vlc_debug( l, "JumpSS <unknown>");
                         break;
                     }
                     // find the VMG
-                    p_vchapter = sys.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchIsVMG, NULL, 0, p_vsegment );
+                    p_vchapter = vm.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                        [](const chapter_codec_cmds_c &data) {
+                            return MatchIsVMG( data); }, p_vsegment );
                     if ( p_vsegment != NULL )
                     {
-                        p_vchapter = p_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchPgcType, &p_type, 1 );
+                        p_vchapter = p_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                            [p_type](const chapter_codec_cmds_c &data) {
+                                return MatchPgcType( data, p_type ); } );
                         if ( p_vchapter != NULL )
                         {
-                            sys.JumpTo( *p_vsegment, *p_vchapter );
+                            vm.JumpTo( *p_vsegment, *p_vchapter );
                             f_result = true;
                         }
                     }
@@ -410,52 +431,62 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
                     switch ( p_type )
                     {
                     case 0x02:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Title Entry", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Title Entry", p_command[4], p_command[3]);
                         break;
                     case 0x03:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Root Menu", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Root Menu", p_command[4], p_command[3]);
                         break;
                     case 0x04:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Subpicture Menu", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Subpicture Menu", p_command[4], p_command[3]);
                         break;
                     case 0x05:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Audio Menu", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Audio Menu", p_command[4], p_command[3]);
                         break;
                     case 0x06:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Angle Menu", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Angle Menu", p_command[4], p_command[3]);
                         break;
                     case 0x07:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) Chapter Menu", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Chapter Menu", p_command[4], p_command[3]);
                         break;
                     default:
-                        msg_Dbg( &sys.demuxer, "JumpSS VTSM (vts %d, ttn %d) <unknown>", p_command[4], p_command[3]);
+                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) <unknown>", p_command[4], p_command[3]);
                         break;
                     }
 
-                    p_vchapter = sys.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchVTSMNumber, &p_command[4], 1, p_vsegment );
+                    {
+                    uint8_t i_vts = p_command[4];
+                    p_vchapter = vm.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                        [i_vts](const chapter_codec_cmds_c &data) {
+                            return MatchVTSMNumber( data,  i_vts ); }, p_vsegment );
 
                     if ( p_vsegment != NULL && p_vchapter != NULL )
                     {
                         // find the title in the VTS
-                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchTitleNumber, &p_command[3], 1 );
+                        uint8_t i_title = p_command[3];
+                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                            [i_title](const chapter_codec_cmds_c &data) {
+                                return MatchTitleNumber( data, i_title ); } );
                         if ( p_vchapter != NULL )
                         {
                             // find the specified menu in the VTSM
-                            p_vchapter = p_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchPgcType, &p_type, 1 );
+                            p_vchapter = p_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                                [p_type](const chapter_codec_cmds_c &data) {
+                                    return MatchPgcType( data, p_type ); } );
                             if ( p_vchapter != NULL )
                             {
-                                sys.JumpTo( *p_vsegment, *p_vchapter );
+                                vm.JumpTo( *p_vsegment, *p_vchapter );
                                 f_result = true;
                             }
                         }
                         else
-                            msg_Dbg( &sys.demuxer, "Title (%d) does not exist in this VTS", p_command[3] );
+                            vlc_debug( l, "Title (%d) does not exist in this VTS", i_title );
                     }
                     else
-                        msg_Dbg( &sys.demuxer, "DVD Domain VTS (%d) not found", p_command[4] );
+                        vlc_debug( l, "DVD Domain VTS (%d) not found", i_vts );
+                    }
                 break;
                 case 3:
-                    msg_Dbg( &sys.demuxer, "JumpSS VMGM (pgc %d)", (p_command[2] << 8) + p_command[3]);
+                    vlc_debug( l, "JumpSS VMGM (pgc %d)", (p_command[2] << 8) + p_command[3]);
                 break;
             }
             break;
@@ -465,61 +496,71 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             uint8_t i_title = p_command[5];
             uint8_t i_ptt = p_command[3];
 
-            msg_Dbg( &sys.demuxer, "JumpVTS Title (%d) PTT (%d)", i_title, i_ptt);
+            vlc_debug( l, "JumpVTS Title (%d) PTT (%d)", i_title, i_ptt);
 
             // find the current VTS content segment
-            p_vchapter = sys.p_current_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchIsDomain, NULL, 0 );
+            p_vchapter = vm.GetCurrentVSegment()->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                [](const chapter_codec_cmds_c &data) {
+                    return MatchIsDomain( data); } );
             if ( p_vchapter != NULL )
             {
                 int16_t i_curr_title = ( p_vchapter->p_chapter )? p_vchapter->p_chapter->GetTitleNumber() : 0;
                 if ( i_curr_title > 0 )
                 {
-                    p_vchapter = sys.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchVTSNumber, &i_curr_title, sizeof(i_curr_title), p_vsegment );
+                    p_vchapter = vm.BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                        [i_curr_title](const chapter_codec_cmds_c &data) {
+                            return MatchVTSNumber( data, i_curr_title ); }, p_vsegment );
 
                     if ( p_vsegment != NULL && p_vchapter != NULL )
                     {
                         // find the title in the VTS
-                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchTitleNumber, &i_title, sizeof(i_title) );
+                        p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                            [i_title](const chapter_codec_cmds_c &data) {
+                                return MatchTitleNumber( data, i_title ); } );
                         if ( p_vchapter != NULL )
                         {
                             // find the chapter in the title
-                            p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchChapterNumber, &i_ptt, sizeof(i_ptt) );
+                            p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                                [i_ptt](const chapter_codec_cmds_c &data) {
+                                    return MatchChapterNumber( data, i_ptt ); } );
                             if ( p_vchapter != NULL )
                             {
-                                sys.JumpTo( *p_vsegment, *p_vchapter );
+                                vm.JumpTo( *p_vsegment, *p_vchapter );
                                 f_result = true;
                             }
                         }
                     else
-                        msg_Dbg( &sys.demuxer, "Title (%d) does not exist in this VTS", i_title );
+                        vlc_debug( l, "Title (%d) does not exist in this VTS", i_title );
                     }
                     else
-                        msg_Dbg( &sys.demuxer, "DVD Domain VTS (%d) not found", i_curr_title );
+                        vlc_debug( l, "DVD Domain VTS (%d) not found", i_curr_title );
                 }
                 else
-                    msg_Dbg( &sys.demuxer, "JumpVTS_PTT command found but not in a VTS(M)");
+                    vlc_debug( l, "JumpVTS_PTT command found but not in a VTS(M)");
             }
             else
-                msg_Dbg( &sys.demuxer, "JumpVTS_PTT command but the DVD domain wasn't found");
+                vlc_debug( l, "JumpVTS_PTT command but the DVD domain wasn't found");
             break;
         }
     case CMD_DVD_SET_GPRMMD:
         {
-            msg_Dbg( &sys.demuxer, "Set GPRMMD [%d]=%d", (p_command[4] << 8) + p_command[5], (p_command[2] << 8) + p_command[3]);
+            vlc_debug( l, "Set GPRMMD [%d]=%d", (p_command[4] << 8) + p_command[5], (p_command[2] << 8) + p_command[3]);
 
             if ( !SetGPRM( (p_command[4] << 8) + p_command[5], (p_command[2] << 8) + p_command[3] ) )
-                msg_Dbg( &sys.demuxer, "Set GPRMMD failed" );
+                vlc_debug( l, "Set GPRMMD failed" );
             break;
         }
     case CMD_DVD_LINKPGCN:
         {
             uint16_t i_pgcn = (p_command[6] << 8) + p_command[7];
 
-            msg_Dbg( &sys.demuxer, "Link PGCN(%d)", i_pgcn );
-            p_vchapter = sys.p_current_vsegment->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchPgcNumber, &i_pgcn, 2 );
+            vlc_debug( l, "Link PGCN(%d)", i_pgcn );
+            p_vchapter = vm.GetCurrentVSegment()->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                [i_pgcn](const chapter_codec_cmds_c &data) {
+                    return MatchPgcNumber( data, i_pgcn ); } );
             if ( p_vchapter != NULL )
             {
-                sys.JumpTo( *sys.p_current_vsegment, *p_vchapter );
+                vm.JumpTo( *vm.GetCurrentVSegment(), *p_vchapter );
                 f_result = true;
             }
             break;
@@ -528,32 +569,34 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
         {
             uint8_t i_cn = p_command[7];
 
-            p_vchapter = sys.p_current_vsegment->CurrentChapter();
+            p_vchapter = vm.GetCurrentVSegment()->CurrentChapter();
 
-            msg_Dbg( &sys.demuxer, "LinkCN (cell %d)", i_cn );
-            p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD, MatchCellNumber, &i_cn, 1 );
+            vlc_debug( l, "LinkCN (cell %d)", i_cn );
+            p_vchapter = p_vchapter->BrowseCodecPrivate( MATROSKA_CHAPTER_CODEC_DVD,
+                [i_cn](const chapter_codec_cmds_c &data) {
+                    return MatchCellNumber( data, i_cn ); } );
             if ( p_vchapter != NULL )
             {
-                sys.JumpTo( *sys.p_current_vsegment, *p_vchapter );
+                vm.JumpTo( *vm.GetCurrentVSegment(), *p_vchapter );
                 f_result = true;
             }
             break;
         }
     case CMD_DVD_GOTO_LINE:
         {
-            msg_Dbg( &sys.demuxer, "GotoLine (%d)", (p_command[6] << 8) + p_command[7] );
+            vlc_debug( l, "GotoLine (%d)", (p_command[6] << 8) + p_command[7] );
             // TODO
             break;
         }
     case CMD_DVD_SET_HL_BTNN1:
         {
-            msg_Dbg( &sys.demuxer, "SetHL_BTN (%d)", p_command[4] );
+            vlc_debug( l, "SetHL_BTN (%d)", p_command[4] );
             SetSPRM( 0x88, p_command[4] );
             break;
         }
     default:
         {
-            msg_Dbg( &sys.demuxer, "unsupported command : %02X %02X %02X %02X %02X %02X %02X %02X"
+            vlc_debug( l, "unsupported command : %02X %02X %02X %02X %02X %02X %02X %02X"
                      ,p_command[0]
                      ,p_command[1]
                      ,p_command[2]
@@ -571,12 +614,12 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
 
 
 
-bool dvd_command_interpretor_c::MatchIsDomain( const chapter_codec_cmds_c &data, const void *, size_t )
+bool dvd_command_interpretor_c::MatchIsDomain( const chapter_codec_cmds_c &data )
 {
     return ( data.p_private_data != NULL && data.p_private_data->GetBuffer()[0] == MATROSKA_DVD_LEVEL_SS );
 }
 
-bool dvd_command_interpretor_c::MatchIsVMG( const chapter_codec_cmds_c &data, const void *, size_t )
+bool dvd_command_interpretor_c::MatchIsVMG( const chapter_codec_cmds_c &data )
 {
     if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
         return false;
@@ -584,102 +627,95 @@ bool dvd_command_interpretor_c::MatchIsVMG( const chapter_codec_cmds_c &data, co
     return ( data.p_private_data->GetBuffer()[0] == MATROSKA_DVD_LEVEL_SS && data.p_private_data->GetBuffer()[1] == 0xC0);
 }
 
-bool dvd_command_interpretor_c::MatchVTSNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchVTSNumber( const chapter_codec_cmds_c &data, uint16_t i_title )
 {
-    if ( i_cookie_size != 2 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_SS || data.p_private_data->GetBuffer()[1] != 0x80 )
         return false;
 
     uint16_t i_gtitle = (data.p_private_data->GetBuffer()[2] << 8 ) + data.p_private_data->GetBuffer()[3];
-    uint16_t i_title = *static_cast<uint16_t const*>( p_cookie );
 
     return (i_gtitle == i_title);
 }
 
-bool dvd_command_interpretor_c::MatchVTSMNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchVTSMNumber( const chapter_codec_cmds_c &data, uint8_t i_title )
 {
-    if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_SS || data.p_private_data->GetBuffer()[1] != 0x40 )
         return false;
 
     uint8_t i_gtitle = data.p_private_data->GetBuffer()[3];
-    uint8_t i_title = *static_cast<uint8_t const*>( p_cookie );
 
     return (i_gtitle == i_title);
 }
 
-bool dvd_command_interpretor_c::MatchTitleNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchTitleNumber( const chapter_codec_cmds_c &data, uint8_t i_title )
 {
-    if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 4 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_TT )
         return false;
 
     uint16_t i_gtitle = (data.p_private_data->GetBuffer()[1] << 8 ) + data.p_private_data->GetBuffer()[2];
-    uint8_t i_title = *static_cast<uint8_t const*>( p_cookie );
 
     return (i_gtitle == i_title);
 }
 
-bool dvd_command_interpretor_c::MatchPgcType( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchPgcType( const chapter_codec_cmds_c &data, uint8_t i_pgc )
 {
-    if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PGC )
         return false;
 
     uint8_t i_pgc_type = data.p_private_data->GetBuffer()[3] & 0x0F;
-    uint8_t i_pgc = *static_cast<uint8_t const*>( p_cookie );
 
     return (i_pgc_type == i_pgc);
 }
 
-bool dvd_command_interpretor_c::MatchPgcNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchPgcNumber( const chapter_codec_cmds_c &data, uint16_t i_pgc_n )
 {
-    if ( i_cookie_size != 2 || data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 8 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PGC )
         return false;
 
-    uint16_t const* i_pgc_n = static_cast<uint16_t const*>( p_cookie );
     uint16_t i_pgc_num = (data.p_private_data->GetBuffer()[1] << 8) + data.p_private_data->GetBuffer()[2];
 
-    return (i_pgc_num == *i_pgc_n);
+    return (i_pgc_num == i_pgc_n);
 }
 
-bool dvd_command_interpretor_c::MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchChapterNumber( const chapter_codec_cmds_c &data, uint8_t i_ptt )
 {
-    if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_PTT )
         return false;
 
     uint8_t i_chapter = data.p_private_data->GetBuffer()[1];
-    uint8_t i_ptt = *static_cast<uint8_t const*>( p_cookie );
 
     return (i_chapter == i_ptt);
 }
 
-bool dvd_command_interpretor_c::MatchCellNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size )
+bool dvd_command_interpretor_c::MatchCellNumber( const chapter_codec_cmds_c &data, uint8_t i_cell_n )
 {
-    if ( i_cookie_size != 1 || data.p_private_data == NULL || data.p_private_data->GetSize() < 5 )
+    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 5 )
         return false;
 
     if ( data.p_private_data->GetBuffer()[0] != MATROSKA_DVD_LEVEL_CN )
         return false;
 
-    uint8_t const* i_cell_n = static_cast<uint8_t const*>( p_cookie );
     uint8_t i_cell_num = data.p_private_data->GetBuffer()[3];
 
-    return (i_cell_num == *i_cell_n);
+    return (i_cell_num == i_cell_n);
 }
 
 const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";
@@ -692,7 +728,7 @@ bool matroska_script_interpretor_c::Interpret( const binary * p_command, size_t
 
     std::string sz_command( reinterpret_cast<const char*> (p_command), i_size );
 
-    msg_Dbg( &sys.demuxer, "command : %s", sz_command.c_str() );
+    vlc_debug( l, "command : %s", sz_command.c_str() );
 
     if ( sz_command.compare( 0, CMD_MS_GOTO_AND_PLAY.size(), CMD_MS_GOTO_AND_PLAY ) == 0 )
     {
@@ -718,17 +754,17 @@ bool matroska_script_interpretor_c::Interpret( const binary * p_command, size_t
         }
 
         std::string st = sz_command.substr( i+1, j-i-1 );
-        int64_t i_chapter_uid = atoll( st.c_str() );
+        chapter_uid i_chapter_uid = std::stoul( st );
 
         virtual_segment_c *p_vsegment;
-        virtual_chapter_c *p_vchapter = sys.FindChapter( i_chapter_uid, p_vsegment );
+        virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, p_vsegment );
 
         if ( p_vchapter == NULL )
-            msg_Dbg( &sys.demuxer, "Chapter %" PRId64 " not found", i_chapter_uid);
+            vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid);
         else
         {
-            if ( !p_vchapter->EnterAndLeave( sys.p_current_vsegment->CurrentChapter() ) )
-                p_vsegment->Seek( sys.demuxer, p_vchapter->i_mk_virtual_start_time, p_vchapter );
+            if ( !p_vchapter->EnterAndLeave( vm.GetCurrentVSegment()->CurrentChapter(), false ) )
+                vm.JumpTo( *p_vsegment, *p_vchapter );
             b_result = true;
         }
     }
@@ -744,7 +780,7 @@ bool matroska_script_codec_c::Enter()
     {
         if ( (*index)->GetSize() )
         {
-            msg_Dbg( &sys.demuxer, "Matroska Script enter command" );
+            vlc_debug( l, "Matroska Script enter command" );
             f_result |= interpreter.Interpret( (*index)->GetBuffer(), (*index)->GetSize() );
         }
         ++index;
@@ -760,7 +796,7 @@ bool matroska_script_codec_c::Leave()
     {
         if ( (*index)->GetSize() )
         {
-            msg_Dbg( &sys.demuxer, "Matroska Script leave command" );
+            vlc_debug( l, "Matroska Script leave command" );
             f_result |= interpreter.Interpret( (*index)->GetBuffer(), (*index)->GetSize() );
         }
         ++index;


=====================================
modules/demux/mkv/chapter_command.hpp
=====================================
@@ -29,23 +29,29 @@
 
 namespace mkv {
 
-const binary MATROSKA_DVD_LEVEL_SS   = 0x30;
-const binary MATROSKA_DVD_LEVEL_LU   = 0x2A;
-const binary MATROSKA_DVD_LEVEL_TT   = 0x28;
-const binary MATROSKA_DVD_LEVEL_PGC  = 0x20;
-const binary MATROSKA_DVD_LEVEL_PG   = 0x18;
-const binary MATROSKA_DVD_LEVEL_PTT  = 0x10;
-const binary MATROSKA_DVD_LEVEL_CN   = 0x08;
+class virtual_chapter_c;
+class virtual_segment_c;
 
-struct demux_sys_t;
+class chapter_codec_vm
+{
+public:
+    virtual virtual_segment_c *GetCurrentVSegment() = 0;
+    virtual virtual_chapter_c *FindVChapter( chapter_uid i_find_uid, virtual_segment_c * & p_vsegment_found ) = 0;
+    virtual void JumpTo( virtual_segment_c &, virtual_chapter_c & ) = 0;
+
+    virtual virtual_chapter_c *BrowseCodecPrivate( enum chapter_codec_id,
+                                                   chapter_cmd_match match,
+                                                   virtual_segment_c * & p_vsegment_found ) = 0;
+};
 
 class chapter_codec_cmds_c
 {
 public:
-    chapter_codec_cmds_c( demux_sys_t & demuxer, enum chapter_codec_id codec_id)
+    chapter_codec_cmds_c( struct vlc_logger *log, chapter_codec_vm & vm_, enum chapter_codec_id codec_id)
     :i_codec_id( codec_id )
     ,p_private_data(NULL)
-    ,sys( demuxer )
+    ,l( log )
+    ,vm( vm_ )
     {}
 
     virtual ~chapter_codec_cmds_c()
@@ -67,7 +73,7 @@ public:
     virtual bool Enter() { return false; }
     virtual bool Leave() { return false; }
     virtual std::string GetCodecName( bool ) const { return ""; }
-    virtual int16_t GetTitleNumber() { return -1; }
+    virtual int16_t GetTitleNumber() const { return -1; }
 
     const enum chapter_codec_id i_codec_id;
 
@@ -78,15 +84,17 @@ protected:
     std::vector<KaxChapterProcessData*> during_cmds;
     std::vector<KaxChapterProcessData*> leave_cmds;
 
-    demux_sys_t & sys;
+    struct vlc_logger *l;
+    chapter_codec_vm & vm;
 };
 
 
 class dvd_command_interpretor_c
 {
 public:
-    dvd_command_interpretor_c( demux_sys_t & demuxer )
-    :sys( demuxer )
+    dvd_command_interpretor_c( struct vlc_logger *log, chapter_codec_vm & vm_ )
+    :l( log )
+    ,vm( vm_ )
     {
         memset( p_PRMs, 0, sizeof(p_PRMs) );
         p_PRMs[ 0x80 + 1 ] = 15;
@@ -188,7 +196,8 @@ protected:
     }
 
     uint16_t       p_PRMs[256];
-    demux_sys_t  & sys;
+    struct vlc_logger *l;
+    chapter_codec_vm & vm;
 
     // DVD command IDs
 
@@ -233,39 +242,42 @@ protected:
     static const uint16_t CMD_DVD_GPREG_AND_VALUE        = 0x7900;
 
     // callbacks when browsing inside CodecPrivate
-    static bool MatchIsDomain     ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchIsVMG        ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchVTSNumber    ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchVTSMNumber   ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchTitleNumber  ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchPgcType      ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchPgcNumber    ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchChapterNumber( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
-    static bool MatchCellNumber   ( const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size );
+    static bool MatchIsDomain     ( const chapter_codec_cmds_c & );
+    static bool MatchIsVMG        ( const chapter_codec_cmds_c & );
+    static bool MatchVTSNumber    ( const chapter_codec_cmds_c &, uint16_t i_title );
+    static bool MatchVTSMNumber   ( const chapter_codec_cmds_c &, uint8_t i_title );
+    static bool MatchTitleNumber  ( const chapter_codec_cmds_c &, uint8_t i_title );
+    static bool MatchPgcType      ( const chapter_codec_cmds_c &, uint8_t i_pgc );
+    static bool MatchPgcNumber    ( const chapter_codec_cmds_c &, uint16_t i_pgc_n );
+    static bool MatchChapterNumber( const chapter_codec_cmds_c &, uint8_t i_ptt );
+    static bool MatchCellNumber   ( const chapter_codec_cmds_c &, uint8_t i_cell_n );
 };
 
 class dvd_chapter_codec_c : public chapter_codec_cmds_c
 {
 public:
-    dvd_chapter_codec_c( demux_sys_t & sys )
-    :chapter_codec_cmds_c( sys, MATROSKA_CHAPTER_CODEC_DVD )
+    dvd_chapter_codec_c( struct vlc_logger *log, chapter_codec_vm & vm_, dvd_command_interpretor_c & intepretor_ )
+    :chapter_codec_cmds_c( log, vm_, MATROSKA_CHAPTER_CODEC_DVD )
+    ,intepretor(intepretor_)
     {}
 
-    bool Enter();
-    bool Leave();
+    bool Enter() override;
+    bool Leave() override;
 
-    std::string GetCodecName( bool f_for_title = false ) const;
-    int16_t GetTitleNumber();
+    std::string GetCodecName( bool f_for_title = false ) const override;
+    int16_t GetTitleNumber() const override;
 
 protected:
     bool EnterLeaveHelper( char const*, std::vector<KaxChapterProcessData*>* );
+    dvd_command_interpretor_c & intepretor;
 };
 
 class matroska_script_interpretor_c
 {
 public:
-    matroska_script_interpretor_c( demux_sys_t & demuxer )
-    :sys( demuxer )
+    matroska_script_interpretor_c( struct vlc_logger *log, chapter_codec_vm & vm_ )
+    :l( log )
+    ,vm( vm_ )
     {}
 
     bool Interpret( const binary * p_command, size_t i_size );
@@ -274,16 +286,17 @@ public:
     static const std::string CMD_MS_GOTO_AND_PLAY;
 
 protected:
-    demux_sys_t  & sys;
+    struct vlc_logger *l;
+    chapter_codec_vm & vm;
 };
 
 
 class matroska_script_codec_c : public chapter_codec_cmds_c
 {
 public:
-    matroska_script_codec_c( demux_sys_t & sys )
-    :chapter_codec_cmds_c( sys, MATROSKA_CHAPTER_CODEC_NATIVE )
-    ,interpreter( sys )
+    matroska_script_codec_c( struct vlc_logger *log, chapter_codec_vm & vm_ )
+    :chapter_codec_cmds_c( log, vm_, MATROSKA_CHAPTER_CODEC_NATIVE )
+    ,interpreter( log, vm_ )
     {}
 
     bool Enter();


=====================================
modules/demux/mkv/chapters.cpp
=====================================
@@ -39,18 +39,14 @@ chapter_item_c::~chapter_item_c()
 }
 
 chapter_item_c *chapter_item_c::BrowseCodecPrivate( chapter_codec_id codec_id,
-                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                    const void *p_cookie,
-                                    size_t i_cookie_size )
+                                                    chapter_cmd_match match )
 {
     // this chapter
-    auto index = codecs.cbegin();
-    while ( index != codecs.cend() )
+    for (const mkv::chapter_codec_cmds_c *index : codecs)
     {
-        if ( (*index)->i_codec_id == codec_id &&
-             match( **index ,p_cookie, i_cookie_size ) )
+        if ( index->i_codec_id == codec_id &&
+             match( *index ) )
             return this;
-        ++index;
     }
     return NULL;
 }
@@ -75,7 +71,7 @@ void chapter_item_c::Append( const chapter_item_c & chapter )
     }
 }
 
-chapter_item_c * chapter_item_c::FindChapter( int64_t i_find_uid )
+chapter_item_c * chapter_item_c::FindChapter( chapter_uid i_find_uid )
 {
     size_t i;
     chapter_item_c *p_result = NULL;
@@ -96,13 +92,11 @@ std::string chapter_item_c::GetCodecName( bool f_for_title ) const
 {
     std::string result;
 
-    auto index = codecs.cbegin();
-    while ( index != codecs.cend() )
+    for (const mkv::chapter_codec_cmds_c *index : codecs)
     {
-        result = (*index)->GetCodecName( f_for_title );
+        result = index->GetCodecName( f_for_title );
         if ( !result.empty () )
             break;
-        ++index;
     }
 
     return result;
@@ -112,13 +106,11 @@ int16_t chapter_item_c::GetTitleNumber( ) const
 {
     int result = -1;
 
-    auto index = codecs.cbegin();
-    while ( index != codecs.cend() )
+    for (const mkv::chapter_codec_cmds_c *index : codecs)
     {
-        result = (*index)->GetTitleNumber( );
+        result = index->GetTitleNumber( );
         if ( result >= 0 )
             break;
-        ++index;
     }
 
     return result;


=====================================
modules/demux/mkv/chapters.hpp
=====================================
@@ -28,6 +28,8 @@
 
 #include "mkv.hpp"
 
+#include <optional>
+
 namespace mkv {
 
 class chapter_translation_c
@@ -47,42 +49,32 @@ public:
     std::vector<uint64_t>  editions;
 };
 
-class chapter_codec_cmds_c;
 class chapter_item_c
 {
 public:
     chapter_item_c()
-    :i_start_time(0)
-    ,i_end_time(-1)
-    ,p_segment_uid(NULL)
-    ,p_segment_edition_uid(NULL)
-    ,b_display_seekpoint(true)
-    ,b_user_display(true)
-    ,p_parent(NULL)
-    ,b_is_leaving(false)
     {}
 
     virtual ~chapter_item_c();
     void Append( const chapter_item_c & edition );
-    chapter_item_c * FindChapter( int64_t i_find_uid );
+    chapter_item_c * FindChapter( chapter_uid i_find_uid );
     virtual chapter_item_c *BrowseCodecPrivate( chapter_codec_id codec_id,
-                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                    const void *p_cookie,
-                                    size_t i_cookie_size );
+                                                chapter_cmd_match match );
     std::string                 GetCodecName( bool f_for_title = false ) const;
     bool                        ParentOf( const chapter_item_c & item ) const;
     int16_t                     GetTitleNumber( ) const;
 
-    vlc_tick_t                  i_start_time, i_end_time;
+    vlc_tick_t                  i_start_time = 0;
+    std::optional<vlc_tick_t>   i_end_time;
     std::vector<chapter_item_c*> sub_chapters;
-    KaxChapterSegmentUID        *p_segment_uid;
-    KaxChapterSegmentEditionUID *p_segment_edition_uid;
-    int64_t                     i_uid;
-    bool                        b_display_seekpoint;
-    bool                        b_user_display;
+    KaxChapterSegmentUID        *p_segment_uid = nullptr;
+    KaxChapterSegmentEditionUID *p_segment_edition_uid = nullptr;
+    chapter_uid                 i_uid = 0;
+    bool                        b_display_seekpoint = true;
+    bool                        b_user_display = true;
     std::string                 str_name;
-    chapter_item_c              *p_parent;
-    bool                        b_is_leaving;
+    chapter_item_c              *p_parent = nullptr;
+    bool                        b_is_leaving = false;
 
     std::vector<chapter_codec_cmds_c*> codecs;
 


=====================================
modules/demux/mkv/demux.cpp
=====================================
@@ -107,7 +107,7 @@ bool demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, matroska_stream_c *
             p_segment1->Preload();
 
             if ( !p_segment1->p_segment_uid ||
-                 FindSegment( *p_segment1->p_segment_uid ) == NULL)
+                 !SegmentIsOpened( *p_segment1->p_segment_uid ) )
             {
                 opened_segments.push_back( p_segment1 );
                 b_keep_stream = true;
@@ -172,9 +172,8 @@ bool demux_sys_t::PreloadLinked()
         return false;
 
     /* Set current chapter */
-    p_current_vsegment->p_current_vchapter = p_current_vsegment->CurrentEdition()->getChapterbyTimecode(0);
-    msg_Dbg( &demuxer, "NEW START CHAPTER uid=%" PRId64, p_current_vsegment->p_current_vchapter && p_current_vsegment->p_current_vchapter->p_chapter ?
-                 p_current_vsegment->p_current_vchapter->p_chapter->i_uid : 0 );
+    msg_Dbg( &demuxer, "NEW START CHAPTER uid=%" PRId64, p_current_vsegment->CurrentChapter() && p_current_vsegment->CurrentChapter()->p_chapter ?
+                 p_current_vsegment->CurrentChapter()->p_chapter->i_uid : 0 );
 
     used_vsegments.push_back( p_current_vsegment );
 
@@ -275,19 +274,20 @@ bool demux_sys_t::FreeUnused()
     return !streams.empty() && !opened_segments.empty();
 }
 
-bool demux_sys_t::PreparePlayback( virtual_segment_c & new_vsegment, vlc_tick_t i_mk_date )
+bool demux_sys_t::PreparePlayback( virtual_segment_c & new_vsegment )
 {
     if ( p_current_vsegment != &new_vsegment )
     {
         if ( p_current_vsegment->CurrentSegment() != NULL )
             p_current_vsegment->CurrentSegment()->ESDestroy();
 
+        if( !new_vsegment.CurrentSegment() )
+            return false;
+
         p_current_vsegment = &new_vsegment;
         p_current_vsegment->CurrentSegment()->ESCreate();
         i_current_title = p_current_vsegment->i_sys_title;
     }
-    if( !p_current_vsegment->CurrentSegment() )
-        return false;
     if( !p_current_vsegment->CurrentSegment()->b_cues )
         msg_Warn( &p_current_vsegment->CurrentSegment()->sys.demuxer, "no cues/empty cues found->seek won't be precise" );
 
@@ -297,10 +297,6 @@ bool demux_sys_t::PreparePlayback( virtual_segment_c & new_vsegment, vlc_tick_t
     p_current_vsegment->CurrentSegment()->InformationCreate( );
     p_current_vsegment->CurrentSegment()->ESCreate( );
 
-    /* Seek to the beginning */
-    p_current_vsegment->Seek(p_current_vsegment->CurrentSegment()->sys.demuxer,
-                             i_mk_date, p_current_vsegment->p_current_vchapter );
-
     return true;
 }
 
@@ -313,26 +309,24 @@ void demux_sys_t::JumpTo( virtual_segment_c & vsegment, virtual_chapter_c & vcha
     }
 }
 
-matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
+bool demux_sys_t::SegmentIsOpened( const EbmlBinary & uid ) const
 {
     for (size_t i=0; i<opened_segments.size(); i++)
     {
         if ( opened_segments[i]->p_segment_uid && *opened_segments[i]->p_segment_uid == uid )
-            return opened_segments[i];
+            return true;
     }
-    return NULL;
+    return false;
 }
 
 virtual_chapter_c *demux_sys_t::BrowseCodecPrivate( chapter_codec_id codec_id,
-                                        bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                        const void *p_cookie,
-                                        size_t i_cookie_size,
-                                        virtual_segment_c * &p_vsegment_found )
+                                                    chapter_cmd_match match,
+                                                    virtual_segment_c * &p_vsegment_found )
 {
     virtual_chapter_c *p_result = NULL;
     for (size_t i=0; i<used_vsegments.size(); i++)
     {
-        p_result = used_vsegments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
+        p_result = used_vsegments[i]->BrowseCodecPrivate( codec_id, match );
         if ( p_result != NULL )
         {
             p_vsegment_found = used_vsegments[i];
@@ -342,7 +336,7 @@ virtual_chapter_c *demux_sys_t::BrowseCodecPrivate( chapter_codec_id codec_id,
     return p_result;
 }
 
-virtual_chapter_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_vsegment_found )
+virtual_chapter_c *demux_sys_t::FindVChapter( chapter_uid i_find_uid, virtual_segment_c * & p_vsegment_found )
 {
     virtual_chapter_c *p_result = NULL;
     for (size_t i=0; i<used_vsegments.size(); i++)


=====================================
modules/demux/mkv/demux.hpp
=====================================
@@ -40,7 +40,7 @@ namespace mkv {
 class virtual_segment_c;
 class chapter_item_c;
 
-struct demux_sys_t
+struct demux_sys_t : public chapter_codec_vm
 {
 public:
     demux_sys_t( demux_t & demux, bool trust_cues )
@@ -55,7 +55,6 @@ public:
         ,i_current_title(0)
         ,i_current_seekpoint(0)
         ,i_updates(0)
-        ,p_current_vsegment(NULL)
         ,i_duration(-1)
         ,trust_cues(trust_cues)
         ,ev(&demux)
@@ -63,7 +62,7 @@ public:
         vlc_mutex_init( &lock_demuxer );
     }
 
-    ~demux_sys_t();
+    virtual ~demux_sys_t();
 
     /* current data */
     demux_t                 & demuxer;
@@ -87,36 +86,41 @@ public:
                     void(*)(input_attachment_t*)>> stored_attachments;
     std::vector<matroska_segment_c*> opened_segments;
     std::vector<virtual_segment_c*>  used_vsegments;
-    virtual_segment_c                *p_current_vsegment;
 
     /* duration of the stream */
     vlc_tick_t              i_duration;
 
     const bool              trust_cues;
 
-    matroska_segment_c *FindSegment( const EbmlBinary & uid ) const;
+    bool SegmentIsOpened( const EbmlBinary & uid ) const;
+
+    // chapter_codec_vm
     virtual_chapter_c *BrowseCodecPrivate( chapter_codec_id codec_id,
-                                        bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                        const void *p_cookie,
-                                        size_t i_cookie_size,
-                                        virtual_segment_c * & p_vsegment_found );
-    virtual_chapter_c *FindChapter( int64_t i_find_uid, virtual_segment_c * & p_vsegment_found );
+                                           chapter_cmd_match match,
+                                           virtual_segment_c * & p_vsegment_found ) override;
+    void JumpTo( virtual_segment_c & vsegment, virtual_chapter_c & vchapter ) override;
+    virtual_segment_c *GetCurrentVSegment() override
+    {
+        return p_current_vsegment;
+    }
+    virtual_chapter_c *FindVChapter( chapter_uid i_find_uid, virtual_segment_c * & p_vsegment_found ) override;
 
     void PreloadFamily( const matroska_segment_c & of_segment );
     bool PreloadLinked();
     bool FreeUnused();
-    bool PreparePlayback( virtual_segment_c & new_vsegment, vlc_tick_t i_mk_date );
+    bool PreparePlayback( virtual_segment_c & new_vsegment );
     bool AnalyseAllSegmentsFound( demux_t *p_demux, matroska_stream_c * );
-    void JumpTo( virtual_segment_c & vsegment, virtual_chapter_c & vchapter );
 
-    dvd_command_interpretor_c & GetDVDInterpretor()
+    dvd_command_interpretor_c * GetDVDInterpretor()
     {
         if (!dvd_interpretor)
         {
-            dvd_interpretor = std::make_unique<dvd_command_interpretor_c>( *this );
-            assert(dvd_interpretor);
+            try {
+                dvd_interpretor = std::make_unique<dvd_command_interpretor_c>( vlc_object_logger( &demuxer ), *this );
+            } catch ( const std::bad_alloc & ) {
+            }
         }
-        return *dvd_interpretor;
+        return dvd_interpretor.get();
     }
 
     uint8_t        palette[4][4];
@@ -126,6 +130,7 @@ public:
     event_thread_t ev;
 
 private:
+    virtual_segment_c                *p_current_vsegment = nullptr;
     std::unique_ptr<dvd_command_interpretor_c> dvd_interpretor;
 };
 


=====================================
modules/demux/mkv/events.cpp
=====================================
@@ -57,17 +57,17 @@ void event_thread_t::SetPci(const pci_t *data)
 #ifndef WORDS_BIGENDIAN
     for( uint8_t button = 1; button <= pci_packet.hli.hl_gi.btn_ns &&
             button < ARRAY_SIZE(pci_packet.hli.btnit); button++) {
-        btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
-        binary *p_data = (binary*) button_ptr;
+        btni_t & button_ptr = pci_packet.hli.btnit[button-1];
+        binary *p_data = (binary*) &button_ptr;
 
         uint16_t i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
         uint16_t i_x_end   = ((p_data[1] & 0x03) << 8 ) + p_data[2];
         uint16_t i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
         uint16_t i_y_end   = ((p_data[4] & 0x03) << 8 ) + p_data[5];
-        button_ptr->x_start = i_x_start;
-        button_ptr->x_end   = i_x_end;
-        button_ptr->y_start = i_y_start;
-        button_ptr->y_end   = i_y_end;
+        button_ptr.x_start = i_x_start;
+        button_ptr.x_end   = i_x_end;
+        button_ptr.y_start = i_y_start;
+        button_ptr.y_end   = i_y_end;
 
     }
     for ( uint8_t i = 0; i<3; i++ )
@@ -165,22 +165,26 @@ void *event_thread_t::EventThread(void *data)
     return NULL;
 }
 
-void event_thread_t::ProcessNavAction( uint16_t button, pci_t* pci )
+void event_thread_t::ProcessNavAction( uint16_t button, const pci_t & pci )
 {
     demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
 
-    if( button <= 0 || button > pci->hli.hl_gi.btn_ns )
+    if( button <= 0 || button > pci.hli.hl_gi.btn_ns )
         return;
 
-    p_sys->GetDVDInterpretor().SetSPRM( 0x88, button );
-    btni_t button_ptr = pci->hli.btnit[button-1];
+    auto interpretor = p_sys->GetDVDInterpretor();
+    if (!interpretor)
+        return;
+
+    interpretor->SetSPRM( 0x88, button );
+    const btni_t & button_ptr = pci.hli.btnit[button-1];
     if ( button_ptr.auto_action_mode )
     {
         vlc_mutex_unlock( &lock );
         vlc_mutex_lock( &p_sys->lock_demuxer );
 
         // process the button action
-        p_sys->GetDVDInterpretor().Interpret( button_ptr.cmd.bytes, 8 );
+        interpretor->Interpret( button_ptr.cmd.bytes, 8 );
 
         vlc_mutex_unlock( &p_sys->lock_demuxer );
         vlc_mutex_lock( &lock );
@@ -192,14 +196,18 @@ void event_thread_t::HandleKeyEvent( EventInfo const& ev )
     msg_Dbg( p_demux, "Handle Key Event");
 
     demux_sys_t* p_sys = (demux_sys_t*)p_demux->p_sys;
-    pci_t *pci = &pci_packet;
+    const pci_t & pci = pci_packet;
+
+    auto interpretor = p_sys->GetDVDInterpretor();
+    if (!interpretor)
+        return;
 
-    uint16_t i_curr_button = p_sys->GetDVDInterpretor().GetSPRM( 0x88 );
+    uint16_t i_curr_button = interpretor->GetSPRM( 0x88 );
 
-    if( i_curr_button <= 0 || i_curr_button > pci->hli.hl_gi.btn_ns )
+    if( i_curr_button <= 0 || i_curr_button > pci.hli.hl_gi.btn_ns )
         return;
 
-    btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
+    const btni_t & button_ptr = pci.hli.btnit[i_curr_button-1];
 
     switch( ev.nav.query )
     {
@@ -213,7 +221,7 @@ void event_thread_t::HandleKeyEvent( EventInfo const& ev )
             vlc_mutex_lock( &p_sys->lock_demuxer );
 
             // process the button action
-            p_sys->GetDVDInterpretor().Interpret( button_ptr.cmd.bytes, 8 );
+            interpretor->Interpret( button_ptr.cmd.bytes, 8 );
 
             vlc_mutex_unlock( &p_sys->lock_demuxer );
             vlc_mutex_lock( &lock );
@@ -230,7 +238,11 @@ void event_thread_t::HandleMouseEvent( EventInfo const& event )
     int x = event.mouse.state_new.i_x;
     int y = event.mouse.state_new.i_y;
 
-    pci_t *pci = &pci_packet;
+    const pci_t & pci = pci_packet;
+
+    auto interpretor = p_sys->GetDVDInterpretor();
+    if (!interpretor)
+        return;
 
     if( vlc_mouse_HasPressed( &event.mouse.state_old, &event.mouse.state_new,
                               MOUSE_BUTTON_LEFT ) )
@@ -244,17 +256,17 @@ void event_thread_t::HandleMouseEvent( EventInfo const& event )
         // get current button
         best = 0;
         dist = 0x08000000; /* >> than  (720*720)+(567*567); */
-        for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
+        for(button = 1; button <= pci.hli.hl_gi.btn_ns; button++)
         {
-            btni_t *button_ptr = &(pci->hli.btnit[button-1]);
+            const btni_t & button_ptr = pci.hli.btnit[button-1];
 
-            if(((unsigned)x >= button_ptr->x_start)
-             && ((unsigned)x <= button_ptr->x_end)
-             && ((unsigned)y >= button_ptr->y_start)
-             && ((unsigned)y <= button_ptr->y_end))
+            if(((unsigned)x >= button_ptr.x_start)
+             && ((unsigned)x <= button_ptr.x_end)
+             && ((unsigned)y >= button_ptr.y_start)
+             && ((unsigned)y <= button_ptr.y_end))
             {
-                mx = (button_ptr->x_start + button_ptr->x_end)/2;
-                my = (button_ptr->y_start + button_ptr->y_end)/2;
+                mx = (button_ptr.x_start + button_ptr.x_end)/2;
+                my = (button_ptr.y_start + button_ptr.y_end)/2;
                 dx = mx - x;
                 dy = my - y;
                 d = (dx*dx) + (dy*dy);
@@ -269,16 +281,16 @@ void event_thread_t::HandleMouseEvent( EventInfo const& event )
 
         if ( best != 0)
         {
-            btni_t button_ptr = pci->hli.btnit[best-1];
-            uint16_t i_curr_button = p_sys->GetDVDInterpretor().GetSPRM( 0x88 );
+            const btni_t & button_ptr = pci.hli.btnit[best-1];
+            uint16_t i_curr_button = interpretor->GetSPRM( 0x88 );
 
             msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
             vlc_mutex_unlock( &lock );
             vlc_mutex_lock( &p_sys->lock_demuxer );
 
             // process the button action
-            p_sys->GetDVDInterpretor().SetSPRM( 0x88, best );
-            p_sys->GetDVDInterpretor().Interpret( button_ptr.cmd.bytes, 8 );
+            interpretor->SetSPRM( 0x88, best );
+            interpretor->Interpret( button_ptr.cmd.bytes, 8 );
 
             msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
 
@@ -297,7 +309,7 @@ void event_thread_t::HandleMouseEvent( EventInfo const& event )
                 uint32_t i_palette;
 
                 if(button_ptr.btn_coln != 0) {
-                    i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
+                    i_palette = pci.hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
                 } else {
                     i_palette = 0;
                 }


=====================================
modules/demux/mkv/events.hpp
=====================================
@@ -111,7 +111,7 @@ private:
     void HandleKeyEvent( EventInfo const& );
     void HandleMouseEvent( EventInfo const& );
 
-    void ProcessNavAction( uint16_t button, pci_t* pci );
+    void ProcessNavAction( uint16_t button, const pci_t & pci );
 
     demux_t      *p_demux;
 


=====================================
modules/demux/mkv/matroska_segment.hpp
=====================================
@@ -76,6 +76,8 @@ public:
     simple_tags_t   simple_tags;
 };
 
+struct demux_sys_t;
+
 class matroska_segment_c
 {
 public:


=====================================
modules/demux/mkv/matroska_segment_parse.cpp
=====================================
@@ -1439,9 +1439,15 @@ void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chap
                 if( MKV_CHECKED_PTR_DECL( p_codec_id, KaxChapterProcessCodecID, cp[j] ) )
                 {
                     if ( p_codec_id->GetValue() == MATROSKA_CHAPTER_CODEC_NATIVE )
-                        p_ccodec = new matroska_script_codec_c( vars.obj->sys );
+                        p_ccodec = new matroska_script_codec_c( vlc_object_logger( &vars.obj->sys.demuxer ), vars.obj->sys );
                     else if ( p_codec_id->GetValue() == MATROSKA_CHAPTER_CODEC_DVD )
-                        p_ccodec = new dvd_chapter_codec_c( vars.obj->sys );
+                    {
+                        auto interepreter = vars.obj->sys.GetDVDInterpretor();
+                        if (unlikely(interepreter == nullptr))
+                            debug( vars, "failed to get the DVD interpreter ");
+                        else
+                            p_ccodec = new dvd_chapter_codec_c( vlc_object_logger( &vars.obj->sys.demuxer ), vars.obj->sys, *interepreter );
+                    }
                     break;
                 }
             }


=====================================
modules/demux/mkv/mkv.cpp
=====================================
@@ -99,7 +99,7 @@ struct demux_sys_t;
 
 static int  Demux  ( demux_t * );
 static int  Control( demux_t *, int, va_list );
-static int  Seek   ( demux_t *, vlc_tick_t i_mk_date, double f_percent, virtual_chapter_c *p_vchapter, bool b_precise = true );
+static int  Seek   ( demux_t *, vlc_tick_t i_mk_date, double f_percent, bool b_precise = true );
 
 /*****************************************************************************
  * Open: initializes matroska demux structures
@@ -256,11 +256,13 @@ static int OpenInternal( demux_t *p_demux, bool trust_cues )
         msg_Warn( p_demux, "This file references other files, you may want to enable the preload of local directory");
 
     if ( !p_sys->PreloadLinked() ||
-         !p_sys->PreparePlayback( *p_sys->p_current_vsegment, 0 ) )
+         !p_sys->PreparePlayback( *p_sys->GetCurrentVSegment() ) )
     {
         msg_Err( p_demux, "cannot use the segment" );
         goto error;
     }
+    /* Seek to the beginning */
+    p_sys->GetCurrentVSegment()->Seek( *p_demux, 0, p_sys->GetCurrentVSegment()->CurrentChapter() );
 
     if (!p_sys->FreeUnused())
     {
@@ -294,7 +296,7 @@ static void Close( vlc_object_t *p_this )
 {
     demux_t     *p_demux = reinterpret_cast<demux_t*>( p_this );
     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
-    virtual_segment_c *p_vsegment = p_sys->p_current_vsegment;
+    virtual_segment_c *p_vsegment = p_sys->GetCurrentVSegment();
     if( p_vsegment )
     {
         matroska_segment_c *p_segment = p_vsegment->CurrentSegment();
@@ -369,7 +371,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             {
                 f = va_arg( args, double );
                 b = va_arg( args, int ); /* precise? */
-                return Seek( p_demux, -1, f, NULL, b );
+                return Seek( p_demux, -1, f, b );
             }
             return VLC_EGENERIC;
 
@@ -397,12 +399,12 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             i_idx = va_arg( args, int );
             if(i_idx <  p_sys->titles.size() && p_sys->titles[i_idx]->i_seekpoint)
             {
-                const int i_edition = p_sys->p_current_vsegment->i_current_edition;
+                const int i_edition = p_sys->GetCurrentVSegment()->i_current_edition;
                 const int i_title = p_sys->i_current_title;
-                p_sys->p_current_vsegment->i_current_edition = i_idx;
+                p_sys->GetCurrentVSegment()->i_current_edition = i_idx;
                 p_sys->i_current_title = i_idx;
                 if( VLC_SUCCESS ==
-                    Seek( p_demux, p_sys->titles[i_idx]->seekpoint[0]->i_time_offset, -1, NULL) )
+                    Seek( p_demux, p_sys->titles[i_idx]->seekpoint[0]->i_time_offset, -1 ) )
                 {
                     p_sys->i_updates |= INPUT_UPDATE_SEEKPOINT|INPUT_UPDATE_TITLE;
                     p_sys->i_current_seekpoint = 0;
@@ -411,7 +413,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                 }
                 else
                 {
-                    p_sys->p_current_vsegment->i_current_edition = i_edition;
+                    p_sys->GetCurrentVSegment()->i_current_edition = i_edition;
                     p_sys->i_current_title = i_title;
                 }
             }
@@ -423,7 +425,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             // TODO change the way it works with the << & >> buttons on the UI (+1/-1 instead of a number)
             if( p_sys->titles.size() && i_skp < p_sys->titles[p_sys->i_current_title]->i_seekpoint)
             {
-                int i_ret = Seek( p_demux, p_sys->titles[p_sys->i_current_title]->seekpoint[i_skp]->i_time_offset, -1, NULL);
+                int i_ret = Seek( p_demux, p_sys->titles[p_sys->i_current_title]->seekpoint[i_skp]->i_time_offset, -1 );
                 if( i_ret == VLC_SUCCESS )
                 {
                     p_sys->i_updates |= INPUT_UPDATE_SEEKPOINT;
@@ -452,18 +454,16 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
         case DEMUX_GET_FPS:
             pf = va_arg( args, double * );
             *pf = 0.0;
-            if( p_sys->p_current_vsegment && p_sys->p_current_vsegment->CurrentSegment() )
+            if( p_sys->GetCurrentVSegment() && p_sys->GetCurrentVSegment()->CurrentSegment() )
             {
-                typedef matroska_segment_c::tracks_map_t tracks_map_t;
-
-                const matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
-                for( tracks_map_t::const_iterator it = p_segment->tracks.begin(); it != p_segment->tracks.end(); ++it )
+                const matroska_segment_c *p_segment = p_sys->GetCurrentVSegment()->CurrentSegment();
+                for( const auto & it : p_segment->tracks )
                 {
-                    const mkv_track_t &track = *it->second;
+                    const auto &track = it.second;
 
-                    if( track.fmt.i_cat == VIDEO_ES && track.fmt.video.i_frame_rate_base > 0 )
+                    if( track->fmt.i_cat == VIDEO_ES && track->fmt.video.i_frame_rate_base > 0 )
                     {
-                        *pf = (double)track.fmt.video.i_frame_rate / track.fmt.video.i_frame_rate_base;
+                        *pf = (double)track->fmt.video.i_frame_rate / track->fmt.video.i_frame_rate_base;
                         break;
                     }
                 }
@@ -474,7 +474,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             i64 = va_arg( args, vlc_tick_t );
             b = va_arg( args, int ); /* precise? */
             msg_Dbg(p_demux,"SET_TIME to %" PRId64, i64 );
-            return Seek( p_demux, i64, -1, NULL, b );
+            return Seek( p_demux, i64, -1, b );
 
         case DEMUX_NAV_ACTIVATE:
         case DEMUX_NAV_UP:
@@ -497,11 +497,10 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
 }
 
 /* Seek */
-static int Seek( demux_t *p_demux, vlc_tick_t i_mk_date, double f_percent, virtual_chapter_c *p_vchapter, bool b_precise )
+static int Seek( demux_t *p_demux, vlc_tick_t i_mk_date, double f_percent, bool b_precise )
 {
     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
-    virtual_segment_c  *p_vsegment = p_sys->p_current_vsegment;
-    matroska_segment_c *p_segment = p_vsegment->CurrentSegment();
+    virtual_segment_c  *p_vsegment = p_sys->GetCurrentVSegment();
 
     if( f_percent < 0 ) msg_Dbg( p_demux, "seek request to i_pos = %" PRId64, i_mk_date );
     else                msg_Dbg( p_demux, "seek request to %.2f%%", f_percent * 100 );
@@ -521,18 +520,13 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_mk_date, double f_percent, virtu
         msg_Warn( p_demux, "cannot seek without duration!");
         return VLC_EGENERIC;
     }
-    if( !p_segment )
-    {
-        msg_Warn( p_demux, "cannot seek without valid segment position");
-        return VLC_EGENERIC;
-    }
 
     /* seek without index or without date */
     if( f_percent >= 0 && (var_InheritBool( p_demux, "mkv-seek-percent" ) || i_mk_date < 0 ))
     {
         i_mk_date = vlc_tick_t( f_percent * p_sys->i_duration );
     }
-    return p_vsegment->Seek( *p_demux, i_mk_date, p_vchapter, b_precise ) ? VLC_SUCCESS : VLC_EGENERIC;
+    return p_vsegment->Seek( *p_demux, i_mk_date, nullptr, b_precise ) ? VLC_SUCCESS : VLC_EGENERIC;
 }
 
 static void ReleaseVpxAlpha(void *opaque)
@@ -549,7 +543,7 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
                   bool b_discardable_picture )
 {
     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
-    matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
+    matroska_segment_c *p_segment = p_sys->GetCurrentVSegment()->CurrentSegment();
 
     KaxInternalBlock& internal_block = simpleblock
         ? static_cast<KaxInternalBlock&>( *simpleblock )
@@ -812,13 +806,13 @@ static int Demux( demux_t *p_demux)
 
     vlc_mutex_locker demux_lock ( &p_sys->lock_demuxer );
 
-    virtual_segment_c  *p_vsegment = p_sys->p_current_vsegment;
+    virtual_segment_c  *p_vsegment = p_sys->GetCurrentVSegment();
 
     if( p_sys->i_pts >= p_sys->i_start_pts )
     {
         if ( p_vsegment->UpdateCurrentToChapter( *p_demux ) )
             return VLC_DEMUXER_SUCCESS;
-        p_vsegment = p_sys->p_current_vsegment;
+        p_vsegment = p_sys->GetCurrentVSegment();
     }
 
     matroska_segment_c *p_segment = p_vsegment->CurrentSegment();


=====================================
modules/demux/mkv/mkv.hpp
=====================================
@@ -48,6 +48,7 @@
 #include <algorithm>
 #include <map>
 #include <stdexcept>
+#include <functional>
 
 /* libebml and matroska */
 #include <ebml/EbmlVersion.h>
@@ -145,6 +146,11 @@ struct matroska_stream_c
     std::vector<matroska_segment_c*> segments;
 };
 
+class chapter_codec_cmds_c;
+using chapter_cmd_match = std::function<bool(const chapter_codec_cmds_c &)>;
+
+using chapter_uid = uint64_t;
+
 
 /*****************************************************************************
  * definitions of structures and functions used by this plugins


=====================================
modules/demux/mkv/util.cpp
=====================================
@@ -314,25 +314,23 @@ error:
 int UpdatePCR( demux_t * p_demux )
 {
     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
-    matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
+    matroska_segment_c *p_segment = p_sys->GetCurrentVSegment()->CurrentSegment();
 
     vlc_tick_t i_pcr = VLC_TICK_INVALID;
 
-    typedef matroska_segment_c::tracks_map_t tracks_map_t;
-
-    for( tracks_map_t::const_iterator it = p_segment->tracks.begin(); it != p_segment->tracks.end(); ++it )
+    for( const auto & it : p_segment->tracks )
     {
-        mkv_track_t &track = *it->second;
+        const auto &track = it.second;
 
-        if( track.i_last_dts == VLC_TICK_INVALID )
+        if( track->i_last_dts == VLC_TICK_INVALID )
             continue;
 
-        if( track.fmt.i_cat != VIDEO_ES && track.fmt.i_cat != AUDIO_ES )
+        if( track->fmt.i_cat != VIDEO_ES && track->fmt.i_cat != AUDIO_ES )
             continue;
 
-        if( track.i_last_dts < i_pcr || i_pcr == VLC_TICK_INVALID )
+        if( track->i_last_dts < i_pcr || i_pcr == VLC_TICK_INVALID )
         {
-            i_pcr = track.i_last_dts;
+            i_pcr = track->i_last_dts;
         }
     }
 
@@ -353,7 +351,7 @@ int UpdatePCR( demux_t * p_demux )
 void send_Block( demux_t * p_demux, mkv_track_t * p_tk, block_t * p_block, unsigned int i_number_frames, int64_t i_duration )
 {
     demux_sys_t *p_sys = (demux_sys_t *)p_demux->p_sys;
-    matroska_segment_c *p_segment = p_sys->p_current_vsegment->CurrentSegment();
+    matroska_segment_c *p_segment = p_sys->GetCurrentVSegment()->CurrentSegment();
 
     if( p_tk->fmt.i_cat == AUDIO_ES && p_tk->i_chans_to_reorder )
     {


=====================================
modules/demux/mkv/virtual_segment.cpp
=====================================
@@ -28,22 +28,22 @@
 
 namespace mkv {
 
-/* FIXME move this, it's demux_sys_t::FindSegment */
+/* FIXME move this, it's demux_sys_t::SegmentIsOpened */
 template<typename T>
-matroska_segment_c * getSegmentbyUID( T * p_uid, std::vector<matroska_segment_c*> & segments )
+matroska_segment_c * getSegmentbyUID( T * p_uid, const std::vector<matroska_segment_c*> & opened_segments )
 {
-    for( size_t i = 0; i < segments.size(); i++ )
+    for( size_t i = 0; i < opened_segments.size(); i++ )
     {
-        if( segments[i]->p_segment_uid &&
-            *p_uid == *(segments[i]->p_segment_uid) )
-            return segments[i];
+        if( opened_segments[i]->p_segment_uid &&
+            *p_uid == *(opened_segments[i]->p_segment_uid) )
+            return opened_segments[i];
     }
     return NULL;
 }
 
 virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_chap,
                                                              matroska_segment_c & main_segment,
-                                                             std::vector<matroska_segment_c*> & segments,
+                                                             const std::vector<matroska_segment_c*> & opened_segments,
                                                              vlc_tick_t & usertime_offset, bool b_ordered)
 {
     std::vector<virtual_chapter_c *> sub_chapters;
@@ -53,9 +53,17 @@ virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_
         return new (std::nothrow) virtual_chapter_c( main_segment, NULL, 0, main_segment.i_duration, sub_chapters );
     }
 
+    if( b_ordered && !p_chap->i_end_time )
+    {
+        msg_Warn( &main_segment.sys.demuxer,
+                  "Missing end time in ordered chapter - ignoring chapter %s",
+                  p_chap->str_name.c_str() );
+        return NULL;
+    }
+
     matroska_segment_c * p_segment = &main_segment;
     if( p_chap->p_segment_uid &&
-       ( !( p_segment = getSegmentbyUID( p_chap->p_segment_uid,segments ) ) || !b_ordered ) )
+       ( !( p_segment = getSegmentbyUID( p_chap->p_segment_uid, opened_segments ) ) || !b_ordered ) )
     {
         msg_Warn( &main_segment.sys.demuxer,
                   "Couldn't find segment 0x%x or not ordered... - ignoring chapter %s",
@@ -70,16 +78,16 @@ virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_
 
     for( size_t i = 0; i < p_chap->sub_chapters.size(); i++ )
     {
-        virtual_chapter_c * p_vsubchap = CreateVirtualChapter( p_chap->sub_chapters[i], *p_segment, segments, tmp, b_ordered );
+        virtual_chapter_c * p_vsubchap = CreateVirtualChapter( p_chap->sub_chapters[i], *p_segment, opened_segments, tmp, b_ordered );
 
         if( p_vsubchap )
             sub_chapters.push_back( p_vsubchap );
     }
     vlc_tick_t stop = ( b_ordered )?
-            (((p_chap->i_end_time == -1 ||
-               (p_chap->i_end_time - p_chap->i_start_time) < (tmp - usertime_offset) )) ? tmp :
-             p_chap->i_end_time - p_chap->i_start_time + usertime_offset )
-            :p_chap->i_end_time;
+            (((!p_chap->i_end_time ||
+               (*p_chap->i_end_time - p_chap->i_start_time) < (tmp - usertime_offset) )) ? tmp :
+             *p_chap->i_end_time - p_chap->i_start_time + usertime_offset )
+            :*p_chap->i_end_time;
 
     virtual_chapter_c * p_vchap = new (std::nothrow) virtual_chapter_c( *p_segment, p_chap, start, stop, sub_chapters );
     if( !p_vchap )
@@ -89,8 +97,8 @@ virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_
         return NULL;
     }
 
-    if ( p_chap->i_end_time >= 0 )
-        usertime_offset += p_chap->i_end_time - p_chap->i_start_time;
+    if ( p_chap->i_end_time && *p_chap->i_end_time >= p_chap->i_start_time )
+        usertime_offset += *p_chap->i_end_time - p_chap->i_start_time;
     else
         usertime_offset = tmp;
 
@@ -108,7 +116,8 @@ virtual_chapter_c::~virtual_chapter_c()
 }
 
 
-virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, matroska_segment_c & main_segment, std::vector<matroska_segment_c*> & opened_segments)
+virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, matroska_segment_c & main_segment,
+                                      const std::vector<matroska_segment_c*> & opened_segments )
 {
     bool b_fake_ordered = false;
     p_edition = p_edit;
@@ -263,9 +272,6 @@ virtual_segment_c::virtual_segment_c( matroska_segment_c & main_segment, std::ve
 {
     /* Main segment */
     std::vector<chapter_edition_c*>::size_type i;
-    i_sys_title = 0;
-    p_current_vchapter = NULL;
-    b_current_vchapter_entered = false;
 
     i_current_edition = main_segment.i_default_edition;
 
@@ -319,6 +325,9 @@ virtual_segment_c::virtual_segment_c( matroska_segment_c & main_segment, std::ve
             break;
         }
     }
+
+    if (CurrentEdition())
+        p_current_vchapter = CurrentEdition()->getChapterbyTimecode(0);
 }
 
 virtual_segment_c::~virtual_segment_c()
@@ -328,29 +337,25 @@ virtual_segment_c::~virtual_segment_c()
 }
 
 virtual_chapter_c *virtual_segment_c::BrowseCodecPrivate( chapter_codec_id codec_id,
-                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                    const void *p_cookie,
-                                    size_t i_cookie_size )
+                                                          chapter_cmd_match match )
 {
     virtual_edition_c * p_ved = CurrentEdition();
     if( p_ved )
-        return p_ved->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
+        return p_ved->BrowseCodecPrivate( codec_id, match );
 
     return NULL;
 }
 
 
 virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( chapter_codec_id codec_id,
-                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                    const void *p_cookie,
-                                    size_t i_cookie_size )
+                                                           chapter_cmd_match match )
 {
     if( !p_edition )
         return NULL;
 
     for( size_t i = 0; i < vchapters.size(); i++ )
     {
-        virtual_chapter_c * p_result = vchapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
+        virtual_chapter_c * p_result = vchapters[i]->BrowseCodecPrivate( codec_id, match );
         if( p_result )
             return p_result;
     }
@@ -360,19 +365,17 @@ virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( chapter_codec_id code
 
 
 virtual_chapter_c * virtual_chapter_c::BrowseCodecPrivate( chapter_codec_id codec_id,
-                                    bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
-                                    const void *p_cookie,
-                                    size_t i_cookie_size )
+                                                           chapter_cmd_match match )
 {
     if( !p_chapter )
         return NULL;
 
-    if( p_chapter->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size ) )
+    if( p_chapter->BrowseCodecPrivate( codec_id, match ) )
         return this;
 
     for( size_t i = 0; i < sub_vchapters.size(); i++ )
     {
-        virtual_chapter_c * p_result = sub_vchapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
+        virtual_chapter_c * p_result = sub_vchapters[i]->BrowseCodecPrivate( codec_id, match );
         if( p_result )
             return p_result;
     }
@@ -523,45 +526,44 @@ bool virtual_segment_c::Seek( demux_t & demuxer, vlc_tick_t i_mk_date,
         /* 1st, we need to know in which chapter we are */
         p_vchapter = CurrentEdition()->getChapterbyTimecode( i_mk_date );
 
-    if ( p_vchapter != NULL && CurrentEdition() )
+    if ( p_vchapter == NULL || !CurrentEdition() )
+        return false;
+
+    vlc_tick_t i_mk_time_offset = p_vchapter->i_mk_virtual_start_time - ( ( p_vchapter->p_chapter )? p_vchapter->p_chapter->i_start_time : 0 );
+    if (CurrentEdition()->b_ordered)
+        p_sys->i_mk_chapter_time = p_vchapter->i_mk_virtual_start_time - p_vchapter->segment.i_mk_start_time - ( ( p_vchapter->p_chapter )? p_vchapter->p_chapter->i_start_time : 0 ) /* + VLC_TICK_0 */;
+    if ( p_vchapter->p_chapter && p_vchapter->i_seekpoint_num > 0 )
     {
-        vlc_tick_t i_mk_time_offset = p_vchapter->i_mk_virtual_start_time - ( ( p_vchapter->p_chapter )? p_vchapter->p_chapter->i_start_time : 0 );
-        if (CurrentEdition()->b_ordered)
-            p_sys->i_mk_chapter_time = p_vchapter->i_mk_virtual_start_time - p_vchapter->segment.i_mk_start_time - ( ( p_vchapter->p_chapter )? p_vchapter->p_chapter->i_start_time : 0 ) /* + VLC_TICK_0 */;
-        if ( p_vchapter->p_chapter && p_vchapter->i_seekpoint_num > 0 )
-        {
-            p_sys->i_updates |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
-            p_sys->i_current_title = i_sys_title;
-            p_sys->i_current_seekpoint = p_vchapter->i_seekpoint_num - 1;
-        }
+        p_sys->i_updates |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
+        p_sys->i_current_title = i_sys_title;
+        p_sys->i_current_seekpoint = p_vchapter->i_seekpoint_num - 1;
+    }
 
-        if( p_current_vchapter == NULL || &p_current_vchapter->segment != &p_vchapter->segment )
+    if( p_current_vchapter == NULL || &p_current_vchapter->segment != &p_vchapter->segment )
+    {
+        // switch to a new Segment
+        if ( p_current_vchapter )
         {
-            if ( p_current_vchapter )
-            {
-                KeepTrackSelection( p_current_vchapter->segment, p_vchapter->segment );
-                p_current_vchapter->segment.ESDestroy();
-            }
-            msg_Dbg( &demuxer, "SWITCH CHAPTER uid=%" PRId64, p_vchapter->p_chapter ? p_vchapter->p_chapter->i_uid : 0 );
-            p_current_vchapter = p_vchapter;
-
-            /* only use for soft linking, hard linking should be continuous */
-            es_out_Control( demuxer.out, ES_OUT_RESET_PCR );
-
-            p_sys->PreparePlayback( *this, i_mk_date );
-            return true;
+            KeepTrackSelection( p_current_vchapter->segment, p_vchapter->segment );
+            p_current_vchapter->segment.ESDestroy();
         }
-        else
-        {
-            p_current_vchapter = p_vchapter;
+        msg_Dbg( &demuxer, "SWITCH CHAPTER uid=%" PRId64, p_vchapter->p_chapter ? p_vchapter->p_chapter->i_uid : 0 );
+        p_current_vchapter = p_vchapter;
 
-            return p_current_vchapter->segment.Seek( demuxer, i_mk_date, i_mk_time_offset, b_precise );
-        }
+        /* only use for soft linking, hard linking should be continuous */
+        es_out_Control( demuxer.out, ES_OUT_RESET_PCR );
+
+        p_sys->PreparePlayback( *this );
     }
-    return false;
+    else
+    {
+        p_current_vchapter = p_vchapter;
+    }
+
+    return p_current_vchapter->segment.Seek( demuxer, i_mk_date, i_mk_time_offset, b_precise );
 }
 
-virtual_chapter_c * virtual_chapter_c::FindChapter( int64_t i_find_uid )
+virtual_chapter_c * virtual_chapter_c::FindChapter( chapter_uid i_find_uid )
 {
     if( p_chapter && ( p_chapter->i_uid == i_find_uid ) )
         return this;
@@ -576,7 +578,7 @@ virtual_chapter_c * virtual_chapter_c::FindChapter( int64_t i_find_uid )
     return NULL;
 }
 
-virtual_chapter_c * virtual_segment_c::FindChapter( int64_t i_find_uid )
+virtual_chapter_c * virtual_segment_c::FindChapter( chapter_uid i_find_uid )
 {
     virtual_edition_c * p_edition = CurrentEdition();
     if (unlikely(p_edition == NULL))
@@ -694,42 +696,40 @@ void virtual_chapter_c::print()
 }
 #endif
 
-void virtual_segment_c::KeepTrackSelection( matroska_segment_c & old, matroska_segment_c & next )
+void virtual_segment_c::KeepTrackSelection( const matroska_segment_c & old, const matroska_segment_c & next )
 {
-    typedef matroska_segment_c::tracks_map_t tracks_map_t;
-
     char *sub_lang = NULL, *aud_lang = NULL;
-    for( tracks_map_t::iterator it = old.tracks.begin(); it != old.tracks.end(); ++it )
+    for( const auto & it : old.tracks )
     {
-        mkv_track_t &track = *it->second;
-        if( track.p_es )
+        const auto &track = it.second;
+        if( track->p_es )
         {
             bool state = false;
-            es_out_Control( old.sys.demuxer.out, ES_OUT_GET_ES_STATE, track.p_es, &state );
+            es_out_Control( old.sys.demuxer.out, ES_OUT_GET_ES_STATE, track->p_es, &state );
             if( state )
             {
-                if( track.fmt.i_cat == AUDIO_ES )
-                    aud_lang = track.fmt.psz_language;
-                else if( track.fmt.i_cat == SPU_ES )
-                    sub_lang = track.fmt.psz_language;
+                if( track->fmt.i_cat == AUDIO_ES )
+                    aud_lang = track->fmt.psz_language;
+                else if( track->fmt.i_cat == SPU_ES )
+                    sub_lang = track->fmt.psz_language;
             }
         }
     }
-    for( tracks_map_t::iterator it = next.tracks.begin(); it != next.tracks.end(); ++it )
+    for( const auto & it : next.tracks )
     {
-        mkv_track_t & new_track = *it->second;
-        es_format_t & new_fmt   = new_track.fmt;
+        const auto & new_track = it.second;
+        es_format_t & new_fmt  = new_track->fmt;
 
         /* Let's only do that for audio and video for now */
         if( new_fmt.i_cat == AUDIO_ES || new_fmt.i_cat == VIDEO_ES )
         {
             /* check for a similar elementary stream */
-            for( tracks_map_t::iterator old_it = old.tracks.begin(); old_it != old.tracks.end(); ++old_it )
+            for( const auto & old_it : old.tracks )
             {
-                mkv_track_t& old_track = *old_it->second;
-                es_format_t& old_fmt = old_track.fmt;
+                const auto & old_track = old_it.second;
+                es_format_t& old_fmt = old_track->fmt;
 
-                if( !old_track.p_es )
+                if( !old_track->p_es )
                     continue;
 
                 if( ( new_fmt.i_cat == old_fmt.i_cat ) &&
@@ -746,21 +746,21 @@ void virtual_segment_c::KeepTrackSelection( matroska_segment_c & old, matroska_s
                         !memcmp( &new_fmt.video, &old_fmt.video, sizeof(video_format_t) ) ) ) )
                 {
                     /* FIXME handle video palettes... */
-                    msg_Warn( &old.sys.demuxer, "Reusing decoder of old track %u for track %u", old_track.i_number, new_track.i_number);
-                    new_track.p_es = old_track.p_es;
-                    old_track.p_es = NULL;
+                    msg_Warn( &old.sys.demuxer, "Reusing decoder of old track %u for track %u", old_track->i_number, new_track->i_number);
+                    new_track->p_es = old_track->p_es;
+                    old_track->p_es = NULL;
                     break;
                 }
             }
         }
-        new_track.fmt.i_priority &= ~(0x10);
+        new_track->fmt.i_priority &= ~(0x10);
         if( ( sub_lang && new_fmt.i_cat == SPU_ES && !strcasecmp(sub_lang, new_fmt.psz_language) ) ||
             ( aud_lang && new_fmt.i_cat == AUDIO_ES && !strcasecmp(aud_lang, new_fmt.psz_language) ) )
         {
             msg_Warn( &old.sys.demuxer, "Since previous segment used lang %s forcing track %u",
-                      new_fmt.psz_language, new_track.i_number );
+                      new_fmt.psz_language, new_track->i_number );
             new_fmt.i_priority |= 0x10;
-            new_track.b_forced = true;
+            new_track->b_forced = true;
         }
     }
 }


=====================================
modules/demux/mkv/virtual_segment.hpp
=====================================
@@ -46,21 +46,17 @@ public:
 
     static virtual_chapter_c * CreateVirtualChapter( chapter_item_c * p_chap,
                                                      matroska_segment_c & main_segment,
-                                                     std::vector<matroska_segment_c*> & segments,
+                                                     const std::vector<matroska_segment_c*> & opened_segments,
                                                      vlc_tick_t & usertime_offset, bool b_ordered );
 
     virtual_chapter_c* getSubChapterbyTimecode( vlc_tick_t time );
     bool Leave( );
     bool EnterAndLeave( virtual_chapter_c *p_leaving_vchapter, bool b_enter = true );
-    virtual_chapter_c * FindChapter( int64_t i_find_uid );
+    virtual_chapter_c * FindChapter( chapter_uid i_find_uid );
     int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level, bool allow_no_name );
 
     virtual_chapter_c * BrowseCodecPrivate( chapter_codec_id codec_id,
-                                            bool (*match)( const chapter_codec_cmds_c &data,
-                                                           const void *p_cookie,
-                                                           size_t i_cookie_size ),
-                                            const void *p_cookie,
-                                            size_t i_cookie_size );
+                                            chapter_cmd_match match );
     bool Enter( bool b_do_subs );
     bool Leave( bool b_do_subs );
 
@@ -85,7 +81,7 @@ public:
 class virtual_edition_c
 {
 public:
-    virtual_edition_c( chapter_edition_c * p_edition, matroska_segment_c & main_segment, std::vector<matroska_segment_c*> & opened_segments );
+    virtual_edition_c( chapter_edition_c * p_edition, matroska_segment_c & main_segment, const std::vector<matroska_segment_c*> & opened_segments );
     ~virtual_edition_c();
     std::vector<virtual_chapter_c*> vchapters;
 
@@ -93,10 +89,7 @@ public:
     std::string GetMainName();
     int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level );
     virtual_chapter_c * BrowseCodecPrivate( chapter_codec_id codec_id,
-                                            bool (*match)( const chapter_codec_cmds_c &data,
-                                                           const void *p_cookie,
-                                                           size_t i_cookie_size ),
-                                             const void *p_cookie, size_t i_cookie_size );
+                                            chapter_cmd_match match );
 
     bool                b_ordered;
     vlc_tick_t          i_duration;
@@ -120,9 +113,8 @@ public:
     ~virtual_segment_c();
     std::vector<virtual_edition_c*> veditions;
     std::vector<virtual_edition_c*>::size_type i_current_edition;
-    virtual_chapter_c               *p_current_vchapter;
-    bool                            b_current_vchapter_entered;
-    int                             i_sys_title;
+    bool                            b_current_vchapter_entered = false;
+    int                             i_sys_title = 0;
 
 
     inline virtual_edition_c * CurrentEdition()
@@ -152,18 +144,16 @@ public:
     inline std::vector<virtual_edition_c*>* Editions() { return &veditions; }
 
     virtual_chapter_c *BrowseCodecPrivate( chapter_codec_id codec_id,
-                                           bool (*match)( const chapter_codec_cmds_c &data,
-                                                          const void *p_cookie,
-                                                          size_t i_cookie_size ),
-                                           const void *p_cookie,
-                                           size_t i_cookie_size );
+                                           chapter_cmd_match match );
 
-    virtual_chapter_c * FindChapter( int64_t i_find_uid );
+    virtual_chapter_c * FindChapter( chapter_uid i_find_uid );
 
     bool UpdateCurrentToChapter( demux_t & demux );
     bool Seek( demux_t & demuxer, vlc_tick_t i_mk_date, virtual_chapter_c *p_vchapter, bool b_precise = true );
 private:
-    void KeepTrackSelection( matroska_segment_c & old, matroska_segment_c & next );
+    void KeepTrackSelection( const matroska_segment_c & old, const matroska_segment_c & next );
+
+    virtual_chapter_c               *p_current_vchapter = nullptr;
 };
 
 } // namespace



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/3db7c59452c860cd9c748bf2145407e9407c33a5...0479c4ab8c5f3f218df61f9cc111dc06e49d2989

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


VideoLAN code repository instance


More information about the vlc-commits mailing list