Coverage Report

Created: 2026-02-05 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mkv/chapter_command_script.cpp
Line
Count
Source
1
// Copyright (C) 2003-2024 VLC authors and VideoLAN
2
// SPDX-License-Identifier: LGPL-2.1-or-later
3
//
4
// chapter_command_script.cpp : Matroska Script Codec for Matroska Chapter Codecs
5
// Authors: Laurent Aimar <fenrir@via.ecp.fr>
6
//          Steve Lhomme <steve.lhomme@free.fr>
7
8
9
#include "chapter_command_script.hpp"
10
#include "virtual_segment.hpp"
11
12
namespace mkv {
13
14
159
#define M_MS_MAX_DEPTH 8
15
//Matroska Script
16
const std::string matroska_script_interpretor_c::CMD_MS_GOTO_AND_PLAY = "GotoAndPlay";
17
18
// see http://www.matroska.org/technical/specs/chapters/index.html#mscript
19
//  for a description of existing commands
20
bool matroska_script_interpretor_c::Interpret( MatroskaChapterProcessTime time, const binary * p_command, size_t i_size )
21
159
{
22
159
    static thread_local int n_call = 0;
23
159
    if( n_call > M_MS_MAX_DEPTH )
24
0
      return false;
25
159
    n_call++;
26
27
159
    bool b_result = false;
28
29
159
    std::string sz_command( reinterpret_cast<const char*> (p_command), i_size );
30
31
159
    vlc_debug( l, "command : %s", sz_command.c_str() );
32
33
159
    if ( sz_command.compare( 0, CMD_MS_GOTO_AND_PLAY.size(), CMD_MS_GOTO_AND_PLAY ) == 0 )
34
16
    {
35
16
        size_t i,j;
36
37
        // find the (
38
20
        for ( i=CMD_MS_GOTO_AND_PLAY.size(); i<sz_command.size(); i++)
39
20
        {
40
20
            if ( sz_command[i] == ' ' )
41
4
                continue;
42
16
            if ( sz_command[i] == '(' )
43
14
            {
44
14
                i++;
45
14
                break;
46
14
            }
47
2
            return false; // extra characters between command and ( is not supported
48
16
        }
49
        // find the )
50
178
        for ( j=i; j<sz_command.size(); j++)
51
171
        {
52
171
            if ( sz_command[j] == ')' )
53
7
            {
54
7
                i--;
55
7
                break;
56
7
            }
57
171
        }
58
59
14
        if(i+1 < j-i-1)
60
6
        {
61
6
            std::string st = sz_command.substr( i+1, j-i-1 );
62
6
            chapter_uid i_chapter_uid = std::stoull( st );
63
64
6
            virtual_segment_c *p_vsegment;
65
6
            virtual_chapter_c *p_vchapter = vm.FindVChapter( i_chapter_uid, p_vsegment );
66
67
6
            if ( p_vchapter == NULL )
68
6
                vlc_debug( l, "Chapter %" PRId64 " not found", i_chapter_uid);
69
0
            else
70
0
            {
71
0
                auto current_chapter = vm.GetCurrentVSegment()->CurrentChapter();
72
0
                if ( p_vchapter == current_chapter) {
73
0
                    if ( time == MATROSKA_CHAPPROCESSTIME_BEFORE )
74
                        // the enter command is enter itself, avoid infinite loop
75
0
                        return false;
76
0
                    vm.JumpTo( *p_vsegment, *p_vchapter );
77
0
                }
78
0
                else if ( !p_vchapter->EnterAndLeave( current_chapter, false ) )
79
0
                    vm.JumpTo( *p_vsegment, *p_vchapter );
80
0
                b_result = true;
81
0
            }
82
6
        }
83
14
    }
84
85
157
    n_call--;
86
157
    return b_result;
87
159
}
88
89
} // namespace