virtual_segment.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:9k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mkv.cpp : matroska demuxer
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2004 the VideoLAN team
  5.  * $Id: 31c2845abc2b496dcc0cdd06ca771c1b4789c6f4 $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Steve Lhomme <steve.lhomme@free.fr>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #include "virtual_segment.hpp"
  25. #include "demux.hpp"
  26. void virtual_segment_c::PrepareChapters( )
  27. {
  28.     if ( linked_segments.size() == 0 )
  29.         return;
  30.     // !!! should be called only once !!!
  31.     matroska_segment_c *p_segment;
  32.     size_t i, j;
  33.     // copy editions from the first segment
  34.     p_segment = linked_segments[0];
  35.     p_editions = &p_segment->stored_editions;
  36.     for ( i=1 ; i<linked_segments.size(); i++ )
  37.     {
  38.         p_segment = linked_segments[i];
  39.         // FIXME assume we have the same editions in all segments
  40.         for (j=0; j<p_segment->stored_editions.size(); j++)
  41.         {
  42.             if( j >= p_editions->size() ) /* Protect against broken files (?) */
  43.                 break;
  44.             (*p_editions)[j]->Append( *p_segment->stored_editions[j] );
  45.         }
  46.     }
  47. }
  48. bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
  49. {
  50.     demux_sys_t & sys = *demux.p_sys;
  51.     chapter_item_c *psz_curr_chapter;
  52.     bool b_has_seeked = false;
  53.     /* update current chapter/seekpoint */
  54.     if ( p_editions->size() )
  55.     {
  56.         /* 1st, we need to know in which chapter we are */
  57.         psz_curr_chapter = (*p_editions)[i_current_edition]->FindTimecode( sys.i_pts, psz_current_chapter );
  58.         /* we have moved to a new chapter */
  59.         if (psz_curr_chapter != NULL && psz_current_chapter != psz_curr_chapter)
  60.         {
  61.             if ( (*p_editions)[i_current_edition]->b_ordered )
  62.             {
  63.                 // Leave/Enter up to the link point
  64.                 b_has_seeked = psz_curr_chapter->EnterAndLeave( psz_current_chapter );
  65.                 if ( !b_has_seeked )
  66.                 {
  67.                     // only physically seek if necessary
  68.                     if ( psz_current_chapter == NULL || (psz_current_chapter->i_end_time != psz_curr_chapter->i_start_time) )
  69.                         Seek( demux, sys.i_pts, 0, psz_curr_chapter, -1 );
  70.                 }
  71.             }
  72.  
  73.             if ( !b_has_seeked )
  74.             {
  75.                 psz_current_chapter = psz_curr_chapter;
  76.                 if ( psz_curr_chapter->i_seekpoint_num > 0 )
  77.                 {
  78.                     demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
  79.                     demux.info.i_title = sys.i_current_title = i_sys_title;
  80.                     demux.info.i_seekpoint = psz_curr_chapter->i_seekpoint_num - 1;
  81.                 }
  82.             }
  83.             return true;
  84.         }
  85.         else if (psz_curr_chapter == NULL)
  86.         {
  87.             // out of the scope of the data described by chapters, leave the edition
  88.             if ( (*p_editions)[i_current_edition]->b_ordered && psz_current_chapter != NULL )
  89.             {
  90.                 if ( !(*p_editions)[i_current_edition]->EnterAndLeave( psz_current_chapter, false ) )
  91.                     psz_current_chapter = NULL;
  92.                 else
  93.                     return true;
  94.             }
  95.         }
  96.     }
  97.     return false;
  98. }
  99. chapter_item_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
  100.                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
  101.                                     const void *p_cookie,
  102.                                     size_t i_cookie_size )
  103. {
  104.     // FIXME don't assume it is the first edition
  105.     std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
  106.     if ( index != p_editions->end() )
  107.     {
  108.         chapter_item_c *p_result = (*index)->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
  109.         if ( p_result != NULL )
  110.             return p_result;
  111.     }
  112.     return NULL;
  113. }
  114. void virtual_segment_c::Sort()
  115. {
  116.     // keep the current segment index
  117.     matroska_segment_c *p_segment = linked_segments[i_current_segment];
  118.     std::sort( linked_segments.begin(), linked_segments.end(), matroska_segment_c::CompareSegmentUIDs );
  119.     for ( i_current_segment=0; i_current_segment<linked_segments.size(); i_current_segment++)
  120.         if ( linked_segments[i_current_segment] == p_segment )
  121.             break;
  122. }
  123. size_t virtual_segment_c::AddSegment( matroska_segment_c *p_segment )
  124. {
  125.     size_t i;
  126.     // check if it's not already in here
  127.     for ( i=0; i<linked_segments.size(); i++ )
  128.     {
  129.         if ( linked_segments[i]->p_segment_uid != NULL
  130.             && p_segment->p_segment_uid != NULL
  131.             && *p_segment->p_segment_uid == *linked_segments[i]->p_segment_uid )
  132.             return 0;
  133.     }
  134.     // find possible mates
  135.     for ( i=0; i<linked_uids.size(); i++ )
  136.     {
  137.         if (   (p_segment->p_segment_uid != NULL && *p_segment->p_segment_uid == linked_uids[i])
  138.             || (p_segment->p_prev_segment_uid != NULL && *p_segment->p_prev_segment_uid == linked_uids[i])
  139.             || (p_segment->p_next_segment_uid !=NULL && *p_segment->p_next_segment_uid == linked_uids[i]) )
  140.         {
  141.             linked_segments.push_back( p_segment );
  142.             AppendUID( p_segment->p_prev_segment_uid );
  143.             AppendUID( p_segment->p_next_segment_uid );
  144.             return 1;
  145.         }
  146.     }
  147.     return 0;
  148. }
  149. void virtual_segment_c::PreloadLinked( )
  150. {
  151.     for ( size_t i=0; i<linked_segments.size(); i++ )
  152.     {
  153.         linked_segments[i]->Preload( );
  154.     }
  155.     i_current_edition = linked_segments[0]->i_default_edition;
  156. }
  157. mtime_t virtual_segment_c::Duration() const
  158. {
  159.     mtime_t i_duration;
  160.     if ( linked_segments.size() == 0 )
  161.         i_duration = 0;
  162.     else {
  163.         matroska_segment_c *p_last_segment = linked_segments[linked_segments.size()-1];
  164. //        p_last_segment->ParseCluster( );
  165.         i_duration = p_last_segment->i_start_time / 1000 + p_last_segment->i_duration;
  166.     }
  167.     return i_duration;
  168. }
  169. void virtual_segment_c::AppendUID( const EbmlBinary * p_UID )
  170. {
  171.     if ( p_UID == NULL )
  172.         return;
  173.     if ( p_UID->GetBuffer() == NULL )
  174.         return;
  175.     for (size_t i=0; i<linked_uids.size(); i++)
  176.     {
  177.         if ( *p_UID == linked_uids[i] )
  178.             return;
  179.     }
  180.     linked_uids.push_back( *(KaxSegmentUID*)(p_UID) );
  181. }
  182. void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter, int64_t i_global_position )
  183. {
  184.     demux_sys_t *p_sys = demuxer.p_sys;
  185.     size_t i;
  186.     // find the actual time for an ordered edition
  187.     if ( psz_chapter == NULL )
  188.     {
  189.         if ( Edition() && Edition()->b_ordered )
  190.         {
  191.             /* 1st, we need to know in which chapter we are */
  192.             psz_chapter = (*p_editions)[i_current_edition]->FindTimecode( i_date, psz_current_chapter );
  193.         }
  194.     }
  195.     if ( psz_chapter != NULL )
  196.     {
  197.         psz_current_chapter = psz_chapter;
  198.         p_sys->i_chapter_time = i_time_offset = psz_chapter->i_user_start_time - psz_chapter->i_start_time;
  199.         if ( psz_chapter->i_seekpoint_num > 0 )
  200.         {
  201.             demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
  202.             demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
  203.             demuxer.info.i_seekpoint = psz_chapter->i_seekpoint_num - 1;
  204.         }
  205.     }
  206.     // find the best matching segment
  207.     for ( i=0; i<linked_segments.size(); i++ )
  208.     {
  209.         if ( i_date < linked_segments[i]->i_start_time )
  210.             break;
  211.     }
  212.     if ( i > 0 )
  213.         i--;
  214.     if ( i_current_segment != i  )
  215.     {
  216.         linked_segments[i_current_segment]->UnSelect();
  217.         linked_segments[i]->Select( i_date );
  218.         i_current_segment = i;
  219.     }
  220.     linked_segments[i]->Seek( i_date, i_time_offset, i_global_position );
  221. }
  222. chapter_item_c *virtual_segment_c::FindChapter( int64_t i_find_uid )
  223. {
  224.     // FIXME don't assume it is the first edition
  225.     std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
  226.     if ( index != p_editions->end() )
  227.     {
  228.         chapter_item_c *p_result = (*index)->FindChapter( i_find_uid );
  229.         if ( p_result != NULL )
  230.             return p_result;
  231.     }
  232.     return NULL;
  233. }