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

Quelle  virtual_segment.cpp   Sprache: C

 

/*****************************************************************************
 * virtual_segment.cpp : virtual segment implementation in the MKV demuxer
 *****************************************************************************
 * Copyright © 2003-2011 VideoLAN and VLC authors
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *          Denis Charmet <typx@dinauz.org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#include "virtual_segment.hpp"

#include <new>

namespace mkv {

/* FIXME move this, it's demux_sys_t::SegmentIsOpened */
template<typename T>
matroska_segment_c * getSegmentbyUID( T * p_uid, const std::vector<matroska_segment_c*> &&nbsp;opened_segments )
{
    for( size_t i = 0; i < opened_segments.size(); 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,
                                                             const std::vector<matroska_segment_c*> & opened_segments,
                                                             vlc_tick_t & usertime_offset, bool b_ordered)
{
    std::vector<virtual_chapter_c *> sub_chapters;
    if( !p_chap )
    {
        /* Dummy chapter use the whole segment */
        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, opened_segments ) ) || !b_ordered ) )
    {
        msg_Warn( &main_segment.sys.demuxer,
                  "Couldn't find segment 0x%x or not ordered... - ignoring chapter %s",
                  *( (uint32_t *) p_chap->p_segment_uid->GetBuffer() ),p_chap->str_name.c_str() );
        return NULL;
    }

    p_segment->Preload();

    vlc_tick_t start = ( b_ordered )? usertime_offset : p_chap->i_start_time;
    vlc_tick_t tmp = usertime_offset;

    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, 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 ||
               (*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 : -1);

    virtual_chapter_c * p_vchap = new (std::nothrow) virtual_chapter_c( *p_segment, p_chap, start, stop, sub_chapters );
    if( !p_vchap )
    {
        for( size_t i = 0 ; i < sub_chapters.size(); i++ )
            delete sub_chapters[i];
        return NULL;
    }

    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;

    msg_Dbg( &main_segment.sys.demuxer,
             "Virtual chapter %s from %" PRId64 " to %" PRId64 " - " ,
             p_chap->str_name.c_str(), p_vchap->i_mk_virtual_start_time, p_vchap->i_mk_virtual_stop_time );

    return p_vchap;
}

virtual_chapter_c::~virtual_chapter_c()
{
    for( size_t i = 0 ; i < sub_vchapters.size(); i++ )
        delete sub_vchapters[i];
}


virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, matroska_segment_c &&nbsp;main_segment,
                                      const std::vector<matroska_segment_c*> & opened_segments )
{
    bool b_fake_ordered = false;
    p_edition = p_edit;
    b_ordered = false;

    vlc_tick_t usertime_offset = 0; // microseconds

    /* ordered chapters */
    if( p_edition && p_edition->b_ordered )
    {
        b_ordered = true;
        for( size_t i = 0; i < p_edition->sub_chapters.size(); i++ )
        {
            virtual_chapter_c * p_vchap = virtual_chapter_c::CreateVirtualChapter( p_edition->sub_chapters[i],
                                                                                   main_segment, opened_segments,
                                                                                   usertime_offset, b_ordered );
            if( p_vchap )
                vchapters.push_back( p_vchap );
        }
        if( vchapters.size() )
            i_duration = vchapters[ vchapters.size() - 1 ]->i_mk_virtual_stop_time;
        else
            i_duration = 0; /* Empty ordered editions will be ignored */
    }
    else /* Not ordered or no edition at all */
    {
        matroska_segment_c * p_cur = &main_segment;
        virtual_chapter_c * p_vchap = NULL;
        vlc_tick_t tmp = 0;

        /* check for prev linked segments */
        /* FIXME to avoid infinite recursion we limit to 10 prev should be better as parameter */
        for( int limit = 0; limit < 10 && p_cur->p_prev_segment_uid ; limit++ )
        {
            matroska_segment_c * p_prev = NULL;
            if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) )
            {
                tmp = 0;
                msg_Dbg( &main_segment.sys.demuxer, "Prev segment 0x%x found\n",
                         *(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() );

                p_prev->Preload();

                /* Create virtual_chapter from the first edition if any */
                chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL;

                p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, *p_prev, opened_segments, tmp, b_ordered );

                if( p_vchap )
                    vchapters.insert( vchapters.begin(), p_vchap );

                p_cur = p_prev;
                b_fake_ordered = true;
            }
            else /* segment not found */
                break;
        }

        tmp = 0;

        /* Append the main segment */
        p_vchap = virtual_chapter_c::CreateVirtualChapter( p_edit, main_segment,
                                                           opened_segments, tmp, b_ordered );
        if( p_vchap )
            vchapters.push_back( p_vchap );

        /* Append next linked segments */
        for( int limit = 0; limit < 10 && p_cur->p_next_segment_uid; limit++ )
        {
            matroska_segment_c * p_next = NULL;
            if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) )
            {
                tmp = 0;
                msg_Dbg( &main_segment.sys.demuxer, "Next segment 0x%x found\n",
                         *(int32_t*) p_cur->p_next_segment_uid->GetBuffer() );

                p_next->Preload();

                /* Create virtual_chapter from the first edition if any */
                chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL;

                 p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, *p_next, opened_segments, tmp, b_ordered );

                if( p_vchap )
                    vchapters.push_back( p_vchap );

                p_cur = p_next;
                b_fake_ordered = true;
            }
            else /* segment not found */
                break;
        }

        /* Retime chapters */
        retimeChapters();
        if(b_fake_ordered)
            b_ordered = true;
    }

#ifdef MKV_DEBUG
    msg_Dbg( &main_segment.sys.demuxer, "-- RECAP-BEGIN --" );
    print();
    msg_Dbg( &main_segment.sys.demuxer, "-- RECAP-END --" );
#endif
}

virtual_edition_c::~virtual_edition_c()
{
    for( size_t i = 0; i < vchapters.size(); i++ )
        delete vchapters[i];
}

void virtual_edition_c::retimeSubChapters( virtual_chapter_c * p_vchap )
{
    vlc_tick_t i_mk_stop_time = p_vchap->i_mk_virtual_stop_time;
    for( size_t i = p_vchap->sub_vchapters.size(); i-- > 0; )
    {
        virtual_chapter_c * p_vsubchap = p_vchap->sub_vchapters[i];
        //p_vsubchap->i_mk_virtual_start_time += p_vchap->i_mk_virtual_start_time;

        /*FIXME we artificially extend stop time if they were there before...*/
        /* Just for comfort*/
        p_vsubchap->i_mk_virtual_stop_time = i_mk_stop_time;
        i_mk_stop_time = p_vsubchap->i_mk_virtual_start_time;

        retimeSubChapters( p_vsubchap );
    }
}

void virtual_edition_c::retimeChapters()
{
    /* This function is just meant to be used on unordered chapters */
    if( b_ordered )
        return;

    i_duration = 0;

    /* On non ordered editions we have one top chapter == one segment */
    for( size_t i = 0; i < vchapters.size(); i++ )
    {
        virtual_chapter_c * p_vchap = vchapters[i];

        p_vchap->i_mk_virtual_start_time = i_duration;
        i_duration += p_vchap->segment.i_duration;
        p_vchap->i_mk_virtual_stop_time = i_duration;

        retimeSubChapters( p_vchap );
    }
}

virtual_segment_c::virtual_segment_c( matroska_segment_c & main_segment, std::vector<matroska_segment_c*> & p_opened_segments )
{
    /* Main segment */
    std::vector<chapter_edition_c*>::size_type i;

    i_current_edition = main_segment.i_default_edition;

    for( i = 0; i < main_segment.stored_editions.size(); i++ )
    {
        /* Create a virtual edition from opened */
        virtual_edition_c * p_vedition = new virtual_edition_c( main_segment.stored_editions[i], main_segment, p_opened_segments );

        bool b_has_translate = false;
        for (size_t j=0; i < p_vedition->vchapters.size(); i++)
        {
            if ( p_vedition->vchapters[j]->segment.translations.size() != 0 )
            {
                b_has_translate = true;
                break;
            }
        }
        /* Ordered empty edition can happen when all chapters are
         * on an other segment which couldn't be found... ignore it */

        /* OK if it has chapters and the translate codec in Matroska */
        if(p_vedition->b_ordered && p_vedition->i_duration == 0 && !b_has_translate)
        {

            msg_Warn( &main_segment.sys.demuxer,
                      "Edition %s (%zu) links to other segments not found and is empty... ignoring it",
                       p_vedition->GetMainName().c_str(), i );
            if(i_current_edition == i)
            {
                msg_Warn( &main_segment.sys.demuxer,
                          "Empty edition was the default... defaulting to 0");
                i_current_edition = 0;
            }
            delete p_vedition;
        }
        else
            veditions.push_back( p_vedition );
    }
    /*if we don't have edition create a dummy one*/
    if( !main_segment.stored_editions.size() )
    {
        virtual_edition_c * p_vedition = new virtual_edition_c( NULL, main_segment, p_opened_segments );
        veditions.push_back( p_vedition );
    }

    /* Get the default edition, if there is none, use the first one */
    for( i = 0; i < veditions.size(); i++)
    {
        if( veditions[i]->p_edition && veditions[i]->p_edition->b_default )
        {
            i_current_edition = i;
            break;
        }
    }

    if (CurrentEdition())
        p_current_vchapter = CurrentEdition()->getChapterbyTimecode(0);
}

virtual_segment_c::~virtual_segment_c()
{
    for( size_t i = 0; i < veditions.size(); i++ )
        delete veditions[i];
}

virtual_chapter_c *virtual_segment_c::BrowseCodecPrivate( chapter_codec_id codec_id,
                                                          chapter_cmd_match match )
{
    virtual_edition_c * p_ved = CurrentEdition();
    if( p_ved )
        return p_ved->BrowseCodecPrivate( codec_id, match );

    return NULL;
}


virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( chapter_codec_id codec_id,
                                                           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 );
        if( p_result )
            return p_result;
    }
    return NULL;
}



virtual_chapter_c * virtual_chapter_c::BrowseCodecPrivate( chapter_codec_id codec_id,
                                                           chapter_cmd_match match )
{
    if( !p_chapter )
        return NULL;

    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 );
        if( p_result )
            return p_result;
    }
    return NULL;
}

bool virtual_chapter_c::ContainsTimestamp( vlc_tick_t time )
{
    /*with the current implementation only the last chapter can have a negative virtual_stop_time*/
    return ( time >= i_mk_virtual_start_time && time < i_mk_virtual_stop_time );
}

virtual_chapter_c* virtual_chapter_c::getSubChapterbyTimecode( vlc_tick_t time )
{
    for( size_t i = 0; i < sub_vchapters.size(); i++ )
    {
        if( sub_vchapters[i]->ContainsTimestamp( time ) )
            return sub_vchapters[i]->getSubChapterbyTimecode( time );
    }

    return this;
}

virtual_chapter_c* virtual_edition_c::getChapterbyTimecode( vlc_tick_t time )
{
    for( size_t i = 0; i < vchapters.size(); i++ )
    {
        if( vchapters[i]->ContainsTimestamp( time ) )
            return vchapters[i]->getSubChapterbyTimecode( time );
    }

    if( vchapters.size() )
    {
        virtual_chapter_c* last_chapter = vchapters.back();

        if( last_chapter->i_mk_virtual_start_time <= time &&
            last_chapter->i_mk_virtual_stop_time < 0 )
        {
            return last_chapter;
        }
    }

    return NULL;
}

bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
{
    demux_sys_t & sys = *(demux_sys_t *)demux.p_sys;
    virtual_chapter_c *p_cur_vchapter = NULL;
    virtual_edition_c *p_cur_vedition = CurrentEdition();

    bool b_has_seeked = false;

    if ( !b_current_vchapter_entered && p_current_vchapter != NULL )
    {
        b_current_vchapter_entered = true;
        if (p_current_vchapter->Enter( true ))
            return true;
    }

    if ( sys.i_pts != VLC_TICK_INVALID )
    {
        if ( p_current_vchapter != NULL && p_current_vchapter->ContainsTimestamp( sys.i_pts - VLC_TICK_0 ))
            p_cur_vchapter = p_current_vchapter;
        else if (p_cur_vedition != NULL)
            p_cur_vchapter = p_cur_vedition->getChapterbyTimecode( sys.i_pts - VLC_TICK_0 );
    }

    /* we have moved to a new chapter */
    if ( p_cur_vchapter != NULL && p_current_vchapter != p_cur_vchapter )
    {
        msg_Dbg( &demux, "New Chapter %" PRId64 " uid=%" PRIu64, sys.i_pts - VLC_TICK_0,
                 p_cur_vchapter->p_chapter ? p_cur_vchapter->p_chapter->i_uid : 0 );
        if ( p_cur_vedition->b_ordered )
        {
            /* FIXME EnterAndLeave has probably been broken for a long time */
            // Leave/Enter up to the link point
            b_has_seeked = p_cur_vchapter->EnterAndLeave( p_current_vchapter );
            if ( !b_has_seeked )
            {
                // only physically seek if necessary
                if ( p_current_vchapter == NULL ||
                    ( p_current_vchapter && &p_current_vchapter->segment != &p_cur_vchapter->segment ) ||
                    ( p_current_vchapter->p_chapter->i_end_time != p_cur_vchapter->p_chapter->i_start_time ))
                {
                    /* Forcing reset pcr */
                    es_out_Control( demux.out, ES_OUT_RESET_PCR);
                    Seek( demux, p_cur_vchapter->i_mk_virtual_start_time, p_cur_vchapter );
                    return true;
                }
                sys.i_start_pts = p_cur_vchapter->i_mk_virtual_start_time + VLC_TICK_0;
                sys.i_mk_chapter_time = p_cur_vchapter->i_mk_virtual_start_time - p_cur_vchapter->segment.i_mk_start_time - ( ( p_cur_vchapter->p_chapter )? p_cur_vchapter->p_chapter->i_start_time : 0 ) /* + VLC_TICK_0 */;
            }
        }

        p_current_vchapter = p_cur_vchapter;
        if ( p_cur_vchapter->i_seekpoint_num > 0 )
        {
            sys.i_updates |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
            sys.i_current_title = i_sys_title;
            sys.i_current_seekpoint = p_cur_vchapter->i_seekpoint_num - 1;
        }

        return b_has_seeked;
    }
    else if ( p_cur_vchapter == NULL && p_cur_vedition != NULL )
    {
        /* out of the scope of the data described by chapters, leave the edition */
        if ( p_cur_vedition->b_ordered && p_current_vchapter != NULL )
        {
            if ( !p_current_vchapter->Leave( ) )
            {
                p_current_vchapter->segment.ESDestroy();
                p_current_vchapter = NULL;
                b_current_vchapter_entered = false;
            }
            else
                return true;
        }
    }
    return false;
}

bool virtual_chapter_c::Leave( )
{
    if( !p_chapter )
        return false;

    return p_chapter->Leave( true );
}

bool virtual_chapter_c::EnterAndLeave( virtual_chapter_c *p_leaving_vchapter, bool b_enter )
{
    if( !p_chapter )
        return false;

    return p_chapter->EnterAndLeave( p_leaving_vchapter->p_chapter, b_enter );
}

bool virtual_segment_c::Seek( demux_t & demuxer, vlc_tick_t i_mk_date,
                              virtual_chapter_c *p_vchapter, bool b_precise )
{
    demux_sys_t *p_sys = (demux_sys_t *)demuxer.p_sys;


    /* find the actual time for an ordered edition */
    if ( p_vchapter == NULL && CurrentEdition() )
        /* 1st, we need to know in which chapter we are */
        p_vchapter = CurrentEdition()->getChapterbyTimecode( i_mk_date );

    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 )
    {
        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 )
    {
        // switch to a new Segment
        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 );
    }
    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( chapter_uid i_find_uid )
{
    if( p_chapter && ( p_chapter->i_uid == i_find_uid ) )
        return this;

    for( size_t i = 0; i < sub_vchapters.size(); i++ )
    {
        virtual_chapter_c * p_res = sub_vchapters[i]->FindChapter( i_find_uid );
        if( p_res )
            return p_res;
    }

    return NULL;
}

virtual_chapter_c * virtual_segment_c::FindChapter( chapter_uid i_find_uid )
{
    virtual_edition_c * p_edition = CurrentEdition();
    if (unlikely(p_edition == NULL))
        return NULL;

    for( size_t i = 0; i < p_edition->vchapters.size(); i++ )
    {
        virtual_chapter_c * p_chapter = p_edition->vchapters[i]->FindChapter( i_find_uid );
        if( p_chapter )
            return p_chapter;
    }
    return NULL;
}

int virtual_chapter_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level, bool allow_no_name )
{
    if ( p_chapter && p_chapter->b_display_seekpoint )
    {
        std::string chap_name;
        if ( p_chapter->b_user_display )
            chap_name = p_chapter->str_name;
        if (chap_name == "")
            chap_name = p_chapter->GetCodecName();

        if (allow_no_name || chap_name != "")
        {
            seekpoint_t *sk = vlc_seekpoint_New();

            if( unlikely( !sk ) )
                return 0;

            sk->i_time_offset = i_mk_virtual_start_time;
            if (chap_name != "")
                sk->psz_name = strdup( chap_name.c_str() );

            /* A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value. */
            title.i_seekpoint++;
            title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
              title.i_seekpoint * sizeof( seekpoint_t* ) );
            title.seekpoint[title.i_seekpoint-1] = sk;

            i_user_chapters++;
        }
    }
    i_seekpoint_num = i_user_chapters;

    for( size_t i = 0; i < sub_vchapters.size(); i++ )
        sub_vchapters[i]->PublishChapters( title, i_user_chapters, i_level + 1, true );

    return i_user_chapters;
}


int virtual_edition_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
{

    /* HACK for now don't expose edition as a seekpoint if its start time is the same than it's first chapter */
    if( vchapters.size() > 0 &&
        vchapters[0]->i_mk_virtual_start_time && p_edition && !p_edition->b_hidden )
    {
        seekpoint_t *sk = vlc_seekpoint_New();

        if( unlikely( !sk ) )
            return 0;

        sk->i_time_offset = 0;
        sk->psz_name = strdup( p_edition->str_name.c_str() );

        title.i_seekpoint++;
        title.seekpoint = static_cast<seekpoint_t**>( xrealloc( title.seekpoint,
                             title.i_seekpoint * sizeof( seekpoint_t* ) ) );
        title.seekpoint[title.i_seekpoint - 1] = sk;
        i_level++;

        i_user_chapters++;
        i_seekpoint_num = i_user_chapters;
    }

//    if( chapters.size() > 1 )
        for( size_t i = 0; i < vchapters.size(); i++ )
            vchapters[i]->PublishChapters( title, i_user_chapters, i_level, false );

    return i_user_chapters;
}

std::string virtual_edition_c::GetMainName()
{
    if( p_edition )
        return p_edition->GetMainName();

    return std::string("");
}

bool virtual_chapter_c::Enter( bool b_do_subs )
{
    if( p_chapter )
        return p_chapter->Enter( b_do_subs );
    return false;
}

bool virtual_chapter_c::Leave( bool b_do_subs )
{
    if( p_chapter )
        return p_chapter->Leave( b_do_subs );
    return false;
}

#ifdef MKV_DEBUG
void virtual_chapter_c::print()
{
    msg_Dbg( &segment.sys.demuxer, "*** chapter %" PRId64 " - %" PRId64 " (%zu)",
             i_mk_virtual_start_time, i_mk_virtual_stop_time, sub_vchapters.size() );
    for( size_t i = 0; i < sub_vchapters.size(); i++ )
        sub_vchapters[i]->print();
}
#endif

void virtual_segment_c::KeepTrackSelection( const matroska_segment_c & old, const matroska_segment_c & next )
{
    char *sub_lang = NULL, *aud_lang = NULL;
    for( const auto & it : old.tracks )
    {
        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 );
            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;
            }
        }
    }
    for( const auto & it : next.tracks )
    {
        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( const auto & old_it : old.tracks )
            {
                const auto & old_track = old_it.second;
                es_format_t& old_fmt = old_track->fmt;

                if( !old_track->p_es )
                    continue;

                if( ( new_fmt.i_cat == old_fmt.i_cat ) &&
                    ( new_fmt.i_codec == old_fmt.i_codec ) &&
                    ( new_fmt.i_priority == old_fmt.i_priority ) &&
                    ( new_fmt.i_bitrate == old_fmt.i_bitrate ) &&
                    ( new_fmt.i_extra == old_fmt.i_extra ) &&
                    ( new_fmt.i_extra == 0 ||
                      !memcmp( new_fmt.p_extra, old_fmt.p_extra, new_fmt.i_extra ) ) &&
                    !strcasecmp( new_fmt.psz_language, old_fmt.psz_language ) &&
                    ( ( new_fmt.i_cat == AUDIO_ES &&
                        !memcmp( &new_fmt.audio, &old_fmt.audio, sizeof(audio_format_t) ) ) ||
                      ( new_fmt.i_cat == VIDEO_ES &&
                        !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;
                    break;
                }
            }
        }
        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.i_priority |= 0x10;
            new_track->b_forced = true;
        }
    }
}

} // namespace

Messung
CHZG
85928888

¤ Dauer der Verarbeitung: 0.10 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.