Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/demux/mkv/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 33 kB image not shown  

Quelle  chapter_command_dvd.cpp   Sprache: C

 

// Copyright (C) 2003-2024 VLC authors and VideoLAN
// SPDX-License-Identifier: LGPL-2.1-or-later
//
// chapter_command_dvd.cpp : DVD codec for Matroska Chapter Codecs
// Authors: Laurent Aimar <fenrir@via.ecp.fr>
//          Steve Lhomme <steve.lhomme@free.fr>


#include "chapter_command_dvd.hpp"
#include "virtual_segment.hpp"

#include <vlc_subpicture.h> // vlc_spu_highlight_t
#include <vlc_bits.h>

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;

int16_t dvd_chapter_codec_c::GetTitleNumber() const
{
    if ( p_private_data != nullptr && p_private_data->GetSize() > 3)
    {
        const binary* p_data = p_private_data->GetBuffer();
        if ( p_data[0] == MATROSKA_DVD_LEVEL_SS )
        {
            return int16_t( (p_data[2] << 8) + p_data[3] );
        }
    }
    return -1;
}

bool dvd_chapter_codec_c::Enter()
{
    return EnterLeaveHelper( "Matroska DVD enter command", enter_cmds, MATROSKA_CHAPPROCESSTIME_BEFORE );
}

bool dvd_chapter_codec_c::Leave()
{
    return EnterLeaveHelper( "Matroska DVD leave command", leave_cmds, MATROSKA_CHAPPROCESSTIME_AFTER );
}

bool dvd_chapter_codec_c::EnterLeaveHelper( char const * str_diag, ChapterProcess & p_container, MatroskaChapterProcessTime process_time )
{
    bool f_result = false;
    ChapterProcess::iterator it = p_container.begin ();
    while( it != p_container.end() )
    {
        if( (*it).GetSize() )
        {
            binary *p_data = (*it).GetBuffer();
            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 )
            {
                vlc_debug( l, "%s", str_diag);
                f_result |= intepretor.Interpret( process_time, p_data, 8 );
            }
        }
        ++it;
    }
    return f_result;
}


std::string dvd_chapter_codec_c::GetCodecName( bool f_for_title ) const
{
    std::string result;
    if ( p_private_data && p_private_data->GetSize() >= 3)
    {
        const binary* p_data = p_private_data->GetBuffer();
/*        if ( p_data[0] == MATROSKA_DVD_LEVEL_TT )
        {
            uint16_t i_title = (p_data[1] << 8) + p_data[2];
            char psz_str[11];
            sprintf( psz_str, " %d  ---", i_title );
            result = "---  DVD Title";
            result += psz_str;
        }
        else */
 if ( p_data[0] == MATROSKA_DVD_LEVEL_LU )
        {
            char psz_str[11];
            snprintf( psz_str, ARRAY_SIZE(psz_str), " (%c%c)  ---", p_data[1], p_data[2] );
            result = "---  DVD Menu";
            result += psz_str;
        }
        else if ( p_data[0] == MATROSKA_DVD_LEVEL_SS && f_for_title )
        {
            if ( p_data[1] == 0x00 )
                result = "First Played";
            else if ( p_data[1] == 0xC0 )
                result = "Video Manager";
            else if ( p_data[1] == 0x80 && p_private_data->GetSize() > 3)
            {
                uint16_t i_title = (p_data[2] << 8) + p_data[3];
                char psz_str[20];
                snprintf( psz_str, ARRAY_SIZE(psz_str), " %d -----", i_title );
                result = "----- Title";
                result += psz_str;
            }
        }
    }

    return result;
}

// see http://www.dvd-replica.com/DVD/vmcmdset.php for a description of DVD commands
bool dvd_command_interpretor_c::Interpret( MatroskaChapterProcessTime, const binary * p_command, size_t i_size )
{
    if ( i_size != 8 )
        return false;

    virtual_segment_c *p_vsegment = NULL;
    virtual_chapter_c *p_vchapter = NULL;
    bool f_result = false;
    uint16_t i_command = ( p_command[0] << 8 ) + p_command[1];

    // handle register tests if there are some
    if ( (i_command & 0xF0) != 0 )
    {
        bool b_test_positive = true;//(i_command & CMD_DVD_IF_NOT) == 0;
        bool b_test_value    = (i_command & CMD_DVD_TEST_VALUE) != 0;
        uint8_t i_test = i_command & 0x70;
        uint16_t i_value;

        // see http://dvd.sourceforge.net/dvdinfo/vmi.html
        uint8_t  i_cr1;
        uint16_t i_cr2;
        switch ( i_command >> 12 )
        {
        default:
            i_cr1 = p_command[3];
            i_cr2 = (p_command[4] << 8) + p_command[5];
            break;
        case 3:
        case 4:
        case 5:
            i_cr1 = p_command[6];
            i_cr2 = p_command[7];
            b_test_value = false;
            break;
        case 6:
        case 7:
            if ( ((p_command[1] >> 4) & 0x7) == 0)
            {
                i_cr1 = p_command[4];
                i_cr2 = (p_command[6] << 8) + p_command[7];
            }
            else
            {
                i_cr1 = p_command[5];
                i_cr2 = (p_command[6] << 8) + p_command[7];
            }
            break;
        }

        if ( b_test_value )
            i_value = i_cr2;
        else
            i_value = GetPRM( i_cr2 );

        switch ( i_test )
        {
        case CMD_DVD_IF_GPREG_EQUAL:
            // if equals
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_NOT_EQUAL:
            // if not equals
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_INF:
            // if inferior
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_INF_EQUAL:
            // if inferior or equal
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_AND:
            // if logical and
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_SUP:
            // if superior
            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;
            }
            break;
        case CMD_DVD_IF_GPREG_SUP_EQUAL:
            // if superior or equal
            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;
            }
            break;
        }

        if ( !b_test_positive )
            return false;
    }

    // strip the test command
    i_command &= 0xFF0F;

    switch ( i_command )
    {
    case CMD_DVD_NOP:
    case CMD_DVD_NOP2:
        {
            vlc_debug( l, "NOP" );
            break;
        }
    case CMD_DVD_BREAK:
        {
            vlc_debug( l, "Break" );
            // TODO
            break;
        }
    case CMD_DVD_JUMP_TT:
        {
            uint8_t i_title = p_command[5];
            vlc_debug( l, "JumpTT %d", i_title );

            // find in the ChapProcessPrivate matching this Title level
            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,
                    [i_cell](const chapter_codec_cmds_c &data) {
                        return MatchCellNumber( data, i_cell );
                    });
                if ( p_vchapter != NULL )
                {
                    vm.JumpTo( *p_vsegment, *p_vchapter );
                    f_result = true;
                }
            }

            break;
        }
    case CMD_DVD_CALLSS_VTSM1:
        {
            vlc_debug( l, "CallSS" );
            binary p_type;
            switch( (p_command[6] & 0xC0) >> 6 ) {
                case 0:
                    p_type = p_command[5] & 0x0F;
                    switch ( p_type )
                    {
                    case 0x00:
                        vlc_debug( l, "CallSS PGC (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x02:
                        vlc_debug( l, "CallSS Title Entry (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x03:
                        vlc_debug( l, "CallSS Root Menu (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x04:
                        vlc_debug( l, "CallSS Subpicture Menu (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x05:
                        vlc_debug( l, "CallSS Audio Menu (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x06:
                        vlc_debug( l, "CallSS Angle Menu (rsm_cell %x)", p_command[4]);
                        break;
                    case 0x07:
                        vlc_debug( l, "CallSS Chapter Menu (rsm_cell %x)", p_command[4]);
                        break;
                    default:
                        vlc_debug( l, "CallSS <unknown> (rsm_cell %x)", p_command[4]);
                        break;
                    }
                    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,
                            [i_cell](const chapter_codec_cmds_c &data) {
                                return MatchCellNumber( data, i_cell ); } );
                        if ( p_vchapter != NULL )
                        {
                            vm.JumpTo( *p_vsegment, *p_vchapter );
                            f_result = true;
                        }
                    }
                break;
                case 1:
                    vlc_debug( l, "CallSS VMGM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
                break;
                case 2:
                    vlc_debug( l, "CallSS VTSM (menu %d, rsm_cell %x)", p_command[5] & 0x0F, p_command[4]);
                break;
                case 3:
                    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:
        {
            vlc_debug( l, "JumpSS");
            binary p_type;
            switch( (p_command[5] & 0xC0) >> 6 ) {
                case 0:
                    vlc_debug( l, "JumpSS FP");
                break;
                case 1:
                    p_type = p_command[5] & 0x0F;
                    switch ( p_type )
                    {
                    case 0x02:
                        vlc_debug( l, "JumpSS VMGM Title Entry");
                        break;
                    case 0x03:
                        vlc_debug( l, "JumpSS VMGM Root Menu");
                        break;
                    case 0x04:
                        vlc_debug( l, "JumpSS VMGM Subpicture Menu");
                        break;
                    case 0x05:
                        vlc_debug( l, "JumpSS VMGM Audio Menu");
                        break;
                    case 0x06:
                        vlc_debug( l, "JumpSS VMGM Angle Menu");
                        break;
                    case 0x07:
                        vlc_debug( l, "JumpSS VMGM Chapter Menu");
                        break;
                    default:
                        vlc_debug( l, "JumpSS <unknown>");
                        break;
                    }
                    // find the VMG
                    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,
                            [p_type](const chapter_codec_cmds_c &data) {
                                return MatchPgcType( data, p_type ); } );
                        if ( p_vchapter != NULL )
                        {
                            vm.JumpTo( *p_vsegment, *p_vchapter );
                            f_result = true;
                        }
                    }
                break;
                case 2:
                    p_type = p_command[5] & 0x0F;
                    switch ( p_type )
                    {
                    case 0x02:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Title Entry", p_command[4], p_command[3]);
                        break;
                    case 0x03:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Root Menu", p_command[4], p_command[3]);
                        break;
                    case 0x04:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Subpicture Menu", p_command[4], p_command[3]);
                        break;
                    case 0x05:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Audio Menu", p_command[4], p_command[3]);
                        break;
                    case 0x06:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Angle Menu", p_command[4], p_command[3]);
                        break;
                    case 0x07:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) Chapter Menu", p_command[4], p_command[3]);
                        break;
                    default:
                        vlc_debug( l, "JumpSS VTSM (vts %d, ttn %d) <unknown>", p_command[4], p_command[3]);
                        break;
                    }

                    {
                    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
                        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,
                                [p_type](const chapter_codec_cmds_c &data) {
                                    return MatchPgcType( data, p_type ); } );
                            if ( p_vchapter != NULL )
                            {
                                vm.JumpTo( *p_vsegment, *p_vchapter );
                                f_result = true;
                            }
                        }
                        else
                            vlc_debug( l, "Title (%d) does not exist in this VTS", i_title );
                    }
                    else
                        vlc_debug( l, "DVD Domain VTS (%d) not found", i_vts );
                    }
                break;
                case 3:
                    vlc_debug( l, "JumpSS VMGM (pgc %d)", (p_command[2] << 8) + p_command[3]);
                break;
            }
            break;
        }
    case CMD_DVD_JUMPVTS_PTT:
        {
            uint8_t i_title = p_command[5];
            uint8_t i_ptt = p_command[3];

            vlc_debug( l, "JumpVTS Title (%d) PTT (%d)", i_title, i_ptt);

            // find the current VTS content segment
            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 = 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,
                            [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,
                                [i_ptt](const chapter_codec_cmds_c &data) {
                                    return MatchChapterNumber( data, i_ptt ); } );
                            if ( p_vchapter != NULL )
                            {
                                vm.JumpTo( *p_vsegment, *p_vchapter );
                                f_result = true;
                            }
                        }
                    else
                        vlc_debug( l, "Title (%d) does not exist in this VTS", i_title );
                    }
                    else
                        vlc_debug( l, "DVD Domain VTS (%d) not found", i_curr_title );
                }
                else
                    vlc_debug( l, "JumpVTS_PTT command found but not in a VTS(M)");
            }
            else
                vlc_debug( l, "JumpVTS_PTT command but the DVD domain wasn't found");
            break;
        }
    case CMD_DVD_SET_GPRMMD:
        {
            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] ) )
                vlc_debug( l, "Set GPRMMD failed" );
            break;
        }
    case CMD_DVD_LINKPGCN:
        {
            uint16_t i_pgcn = (p_command[6] << 8) + p_command[7];

            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 )
            {
                vm.JumpTo( *vm.GetCurrentVSegment(), *p_vchapter );
                f_result = true;
            }
            break;
        }
    case CMD_DVD_LINKCN:
        {
            uint8_t i_cn = p_command[7];

            p_vchapter = vm.GetCurrentVSegment()->CurrentChapter();

            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 )
            {
                vm.JumpTo( *vm.GetCurrentVSegment(), *p_vchapter );
                f_result = true;
            }
            break;
        }
    case CMD_DVD_GOTO_LINE:
        {
            vlc_debug( l, "GotoLine (%d)", (p_command[6] << 8) + p_command[7] );
            // TODO
            break;
        }
    case CMD_DVD_SET_HL_BTNN1:
        {
            vlc_debug( l, "SetHL_BTN (%d)", p_command[4] );
            SetSPRM( 0x88, p_command[4] );
            break;
        }
    default:
        {
            vlc_debug( l, "unsupported command : %02X %02X %02X %02X %02X %02X %02X %02X"
                     ,p_command[0]
                     ,p_command[1]
                     ,p_command[2]
                     ,p_command[3]
                     ,p_command[4]
                     ,p_command[5]
                     ,p_command[6]
                     ,p_command[7]);
            break;
        }
    }

    return f_result;
}

bool dvd_command_interpretor_c::ProcessNavAction( uint16_t button )
{
    const pci_t & pci = pci_packet;

    if( button == 0 || button > pci.hli.hl_gi.btn_ns || button > ARRAY_SIZE(pci.hli.btnit) )
        return false;

    SetSPRM( 0x88, button );
    const btni_t & button_ptr = pci.hli.btnit[button-1];
    if ( button_ptr.auto_action_mode )
    {
        // process the button action
        return Interpret( MATROSKA_CHAPPROCESSTIME_DURING, button_ptr.cmd.bytes, 8 );
    }
    return false;
}

bool dvd_command_interpretor_c::HandleKeyEvent( NavivationKey key )
{
    const pci_t & pci = pci_packet;
    uint16_t i_curr_button = GetSPRM( 0x88 );

    if( i_curr_button == 0 || i_curr_button > pci.hli.hl_gi.btn_ns || i_curr_button > ARRAY_SIZE(pci.hli.btnit) )
        return false;

    const btni_t & button_ptr = pci.hli.btnit[i_curr_button-1];

    switch( key )
    {
    case LEFT:  return ProcessNavAction( button_ptr.left );
    case RIGHT: return ProcessNavAction( button_ptr.right );
    case UP:    return ProcessNavAction( button_ptr.up );
    case DOWN:  return ProcessNavAction( button_ptr.down );
    case OK:
        // process the button action
        return Interpret( MATROSKA_CHAPPROCESSTIME_DURING, button_ptr.cmd.bytes, 8 );
    case MENU:
    case POPUP:
        return false;
    }
    vlc_assert_unreachable();
}

void dvd_command_interpretor_c::HandleMousePressed( unsigned x, unsigned y )
{
    const pci_t & pci = pci_packet;

    uint16_t best;
    uint32_t dist,d;
    int32_t mx,my,dx,dy;

    // get current button
    best = 0;
    dist = std::numeric_limits<uint32_t>::max(); /* >> than  (720*720)+(567*567); */
    for(uint16_t button = 1; button <= std::min<uint16_t>(pci.hli.hl_gi.btn_ns, ARRAY_SIZE(pci.hli.btnit)); button++)
    {
        const btni_t & button_ptr = pci.hli.btnit[button-1];

        if((x >= button_ptr.x_start)
            && (x <= button_ptr.x_end)
            && (y >= button_ptr.y_start)
            && (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;
            dx = mx - x;
            dy = my - y;
            d = (dx*dx) + (dy*dy);
            /* If the mouse is within the button and the mouse is closer
            * to the center of this button then it is the best choice. */

            if(d < dist) {
                dist = d;
                best = button;
            }
        }
    }

    if ( best == 0)
        return;

    const btni_t & button_ptr = pci.hli.btnit[best-1];
    uint16_t i_curr_button = GetSPRM( 0x88 );

    vlc_debug( l, "Clicked button %" PRIu16, best );

    // process the button action
    SetSPRM( 0x88, best );
    Interpret( MATROSKA_CHAPPROCESSTIME_DURING, button_ptr.cmd.bytes, 8 );

    vlc_debug( l, "Processed button %" PRIu16, best );

    // select new button
    if ( best != i_curr_button )
    {
        // TODO: make sure we do not overflow in the conversion
        vlc_spu_highlight_t spu_hl = vlc_spu_highlight_t();

        spu_hl.x_start = (int)button_ptr.x_start;
        spu_hl.y_start = (int)button_ptr.y_start;

        spu_hl.x_end = (int)button_ptr.x_end;
        spu_hl.y_end = (int)button_ptr.y_end;

        uint32_t i_palette;

        if(button_ptr.btn_coln != 0) {
            i_palette = pci.hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
        } else {
            i_palette = 0;
        }

        for( int i = 0; i < 4; i++ )
        {
            uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
            uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
            i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;

            spu_hl.palette.palette[i][0] = (i_yuv >> 16) & 0xff;
            spu_hl.palette.palette[i][1] = (i_yuv >> 0) & 0xff;
            spu_hl.palette.palette[i][2] = (i_yuv >> 8) & 0xff;
            spu_hl.palette.palette[i][3] = i_alpha;
        }

        vm.SetHighlight( spu_hl );
    }
}

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 )
{
    if ( data.p_private_data == NULL || data.p_private_data->GetSize() < 2 )
        return false;

    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, uint16_t i_title )
{
    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];

    return (i_gtitle == i_title);
}

bool dvd_command_interpretor_c::MatchVTSMNumber( const chapter_codec_cmds_c &data, uint8_t i_title )
{
    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];

    return (i_gtitle == i_title);
}

bool dvd_command_interpretor_c::MatchTitleNumber( const chapter_codec_cmds_c &data, uint8_t i_title )
{
    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];

    return (i_gtitle == i_title);
}

bool dvd_command_interpretor_c::MatchPgcType( const chapter_codec_cmds_c &data, uint8_t i_pgc )
{
    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;

    return (i_pgc_type == i_pgc);
}

bool dvd_command_interpretor_c::MatchPgcNumber( const chapter_codec_cmds_c &data, uint16_t i_pgc_n )
{
    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 i_pgc_num = (data.p_private_data->GetBuffer()[1] << 8) + data.p_private_data->GetBuffer()[2];

    return (i_pgc_num == i_pgc_n);
}

bool dvd_command_interpretor_c::MatchChapterNumber( const chapter_codec_cmds_c &data, uint8_t i_ptt )
{
    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];

    return (i_chapter == i_ptt);
}

bool dvd_command_interpretor_c::MatchCellNumber( const chapter_codec_cmds_c &data, uint8_t i_cell_n )
{
    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 i_cell_num = data.p_private_data->GetBuffer()[3];

    return (i_cell_num == i_cell_n);
}

void dvd_command_interpretor_c::SetPci(const uint8_t *data, unsigned size)
{
    if (size < PCI_RAW_SIZE)
        return;

    bs_t bs;
    bs_init(&bs, data, size);

    pci_packet.pci_gi.nv_pck_lbn = bs_read(&bs, 32);
    pci_packet.pci_gi.vobu_cat   = bs_read(&bs, 16);
    bs_skip(&bs, 16);

    bs_skip(&bs, 7);
    pci_packet.pci_gi.vobu_uop_ctl.video_pres_mode_change = bs_read1(&bs);

    pci_packet.pci_gi.vobu_uop_ctl.karaoke_audio_pres_mode_change = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.angle_change           = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.subpic_stream_change   = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.audio_stream_change    = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.pause_on               = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.still_off              = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.button_select_or_activate = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.resume                 = bs_read1(&bs);

    pci_packet.pci_gi.vobu_uop_ctl.chapter_menu_call      = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.angle_menu_call        = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.audio_menu_call        = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.subpic_menu_call       = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.root_menu_call         = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.title_menu_call        = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.backward_scan          = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.forward_scan           = bs_read1(&bs);

    pci_packet.pci_gi.vobu_uop_ctl.next_pg_search         = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.prev_or_top_pg_search  = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.time_or_chapter_search = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.go_up                  = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.stop                   = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.title_play             = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.chapter_search_or_play = bs_read1(&bs);
    pci_packet.pci_gi.vobu_uop_ctl.title_or_time_play     = bs_read1(&bs);

    pci_packet.pci_gi.vobu_s_ptm    = bs_read(&bs, 32);
    pci_packet.pci_gi.vobu_e_ptm    = bs_read(&bs, 32);
    pci_packet.pci_gi.vobu_se_e_ptm = bs_read(&bs, 32);

    pci_packet.pci_gi.e_eltm.hour    = bs_read(&bs, 8);
    pci_packet.pci_gi.e_eltm.minute  = bs_read(&bs, 8);
    pci_packet.pci_gi.e_eltm.second  = bs_read(&bs, 8);
    pci_packet.pci_gi.e_eltm.frame_u = bs_read(&bs, 8);

    // FIXME read buffer in one pass using bs_t
    for (size_t i = 0; i < ARRAY_SIZE(pci_packet.pci_gi.vobu_isrc); i++)
        pci_packet.pci_gi.vobu_isrc[i] = bs_read(&bs, 8);

    for (size_t i = 0; i < ARRAY_SIZE(pci_packet.nsml_agli.nsml_agl_dsta); i++)
        pci_packet.nsml_agli.nsml_agl_dsta[i] = bs_read(&bs, 32);

    pci_packet.hli.hl_gi.hli_ss       = bs_read(&bs, 16);
    pci_packet.hli.hl_gi.hli_s_ptm    = bs_read(&bs, 32);
    pci_packet.hli.hl_gi.hli_e_ptm    = bs_read(&bs, 32);
    pci_packet.hli.hl_gi.btn_se_e_ptm = bs_read(&bs, 32);
    bs_skip(&bs, 2);
    pci_packet.hli.hl_gi.btngr_ns      = bs_read(&bs, 2);
    bs_skip(&bs, 1);
    pci_packet.hli.hl_gi.btngr1_dsp_ty = bs_read(&bs, 3);
    bs_skip(&bs, 1);
    pci_packet.hli.hl_gi.btngr2_dsp_ty = bs_read(&bs, 3);
    bs_skip(&bs, 1);
    pci_packet.hli.hl_gi.btngr3_dsp_ty = bs_read(&bs, 3);
    pci_packet.hli.hl_gi.btn_ofn       = bs_read(&bs, 8);
    pci_packet.hli.hl_gi.btn_ns        = bs_read(&bs, 8);
    pci_packet.hli.hl_gi.nsl_btn_ns    = bs_read(&bs, 8);
    bs_skip(&bs, 8);
    pci_packet.hli.hl_gi.fosl_btnn     = bs_read(&bs, 8);
    pci_packet.hli.hl_gi.foac_btnn     = bs_read(&bs, 8);

    for (size_t i = 0; i < 3; i++)
        for (size_t j = 0; j < 2; j++)
            pci_packet.hli.btn_colit.btn_coli[i][j] = bs_read(&bs, 32 );

    for (size_t i = 0; i < ARRAY_SIZE(pci_packet.hli.btnit); i++)
    {
        auto & btn = pci_packet.hli.btnit[i];
        btn.btn_coln = bs_read(&bs, 2);
        btn.x_start  = bs_read(&bs, 10);
        bs_skip(&bs, 2);
        btn.x_end    = bs_read(&bs, 10);

        btn.auto_action_mode = bs_read(&bs, 2);
        btn.y_start = bs_read(&bs, 10);
        bs_skip(&bs, 2);
        btn.y_end   = bs_read(&bs, 10);

        bs_skip(&bs, 2);
        btn.up = bs_read(&bs, 6);

        bs_skip(&bs, 2);
        btn.down    = bs_read(&bs, 6);
        bs_skip(&bs, 2);
        btn.left    = bs_read(&bs, 6);
        bs_skip(&bs, 2);
        btn.right   = bs_read(&bs, 6);

        // FIXME read buffer in one pass using bs_t
        for (size_t i = 0; i < ARRAY_SIZE(btn.cmd.bytes); i++)
            btn.cmd.bytes[i] = bs_read(&bs, 8);
    }
    bs_skip(&bs, 8*189);
    assert(!bs_error(&bs));
}

} // namespace

Messung
CHZG
85939892

¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.