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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mkv.cpp : matroska demuxer
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2004 the VideoLAN team
  5.  * $Id: eb359baf78b4f67a1ce476edfaf09785c598396a $
  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 "chapters.hpp"
  25. #include "chapter_command.hpp"
  26. chapter_item_c::~chapter_item_c()
  27. {
  28.     std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
  29.     while ( index != codecs.end() )
  30.     {
  31.         delete (*index);
  32.         index++;
  33.     }
  34.     std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
  35.     while ( index_ != sub_chapters.end() )
  36.     {
  37.         delete (*index_);
  38.         index_++;
  39.     }
  40. }
  41. int chapter_item_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
  42. {
  43.     // add support for meta-elements from codec like DVD Titles
  44.     if ( !b_display_seekpoint || psz_name == "" )
  45.     {
  46.         psz_name = GetCodecName();
  47.         if ( psz_name != "" )
  48.             b_display_seekpoint = true;
  49.     }
  50.     if (b_display_seekpoint)
  51.     {
  52.         seekpoint_t *sk = vlc_seekpoint_New();
  53.         sk->i_level = i_level;
  54.         sk->i_time_offset = i_start_time;
  55.         sk->psz_name = strdup( psz_name.c_str() );
  56.         // A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value.
  57.         title.i_seekpoint++;
  58.         title.seekpoint = (seekpoint_t**)realloc( title.seekpoint, title.i_seekpoint * sizeof( seekpoint_t* ) );
  59.         title.seekpoint[title.i_seekpoint-1] = sk;
  60.         if ( b_user_display )
  61.             i_user_chapters++;
  62.     }
  63.     for ( size_t i=0; i<sub_chapters.size() ; i++)
  64.     {
  65.         sub_chapters[i]->PublishChapters( title, i_user_chapters, i_level+1 );
  66.     }
  67.     i_seekpoint_num = i_user_chapters;
  68.     return i_user_chapters;
  69. }
  70. chapter_item_c *chapter_item_c::BrowseCodecPrivate( unsigned int codec_id,
  71.                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
  72.                                     const void *p_cookie,
  73.                                     size_t i_cookie_size )
  74. {
  75.     // this chapter
  76.     std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
  77.     while ( index != codecs.end() )
  78.     {
  79.         if ( match( **index ,p_cookie, i_cookie_size ) )
  80.             return this;
  81.         index++;
  82.     }
  83.  
  84.     // sub-chapters
  85.     chapter_item_c *p_result = NULL;
  86.     std::vector<chapter_item_c*>::const_iterator index2 = sub_chapters.begin();
  87.     while ( index2 != sub_chapters.end() )
  88.     {
  89.         p_result = (*index2)->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
  90.         if ( p_result != NULL )
  91.             return p_result;
  92.         index2++;
  93.     }
  94.  
  95.     return p_result;
  96. }
  97. void chapter_item_c::Append( const chapter_item_c & chapter )
  98. {
  99.     // we are appending content for the same chapter UID
  100.     size_t i;
  101.     chapter_item_c *p_chapter;
  102.     for ( i=0; i<chapter.sub_chapters.size(); i++ )
  103.     {
  104.         p_chapter = FindChapter( chapter.sub_chapters[i]->i_uid );
  105.         if ( p_chapter != NULL )
  106.         {
  107.             p_chapter->Append( *chapter.sub_chapters[i] );
  108.         }
  109.         else
  110.         {
  111.             sub_chapters.push_back( chapter.sub_chapters[i] );
  112.         }
  113.     }
  114.     i_user_start_time = min( i_user_start_time, chapter.i_user_start_time );
  115.     i_user_end_time = max( i_user_end_time, chapter.i_user_end_time );
  116. }
  117. chapter_item_c * chapter_item_c::FindChapter( int64_t i_find_uid )
  118. {
  119.     size_t i;
  120.     chapter_item_c *p_result = NULL;
  121.     if ( i_uid == i_find_uid )
  122.         return this;
  123.     for ( i=0; i<sub_chapters.size(); i++)
  124.     {
  125.         p_result = sub_chapters[i]->FindChapter( i_find_uid );
  126.         if ( p_result != NULL )
  127.             break;
  128.     }
  129.     return p_result;
  130. }
  131. std::string chapter_item_c::GetCodecName( bool f_for_title ) const
  132. {
  133.     std::string result;
  134.     std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
  135.     while ( index != codecs.end() )
  136.     {
  137.         result = (*index)->GetCodecName( f_for_title );
  138.         if ( result != "" )
  139.             break;
  140.         index++;
  141.     }
  142.     return result;
  143. }
  144. int16 chapter_item_c::GetTitleNumber( ) const
  145. {
  146.     int result = -1;
  147.     std::vector<chapter_codec_cmds_c*>::const_iterator index = codecs.begin();
  148.     while ( index != codecs.end() )
  149.     {
  150.         result = (*index)->GetTitleNumber( );
  151.         if ( result >= 0 )
  152.             break;
  153.         index++;
  154.     }
  155.     return result;
  156. }
  157. int64_t chapter_item_c::RefreshChapters( bool b_ordered, int64_t i_prev_user_time )
  158. {
  159.     int64_t i_user_time = i_prev_user_time;
  160.  
  161.     // first the sub-chapters, and then ourself
  162.     std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
  163.     while ( index != sub_chapters.end() )
  164.     {
  165.         i_user_time = (*index)->RefreshChapters( b_ordered, i_user_time );
  166.         index++;
  167.     }
  168.     if ( b_ordered )
  169.     {
  170.         // the ordered chapters always start at zero
  171.         if ( i_prev_user_time == -1 )
  172.         {
  173.             if ( i_user_time == -1 )
  174.                 i_user_time = 0;
  175.             i_prev_user_time = 0;
  176.         }
  177.         i_user_start_time = i_prev_user_time;
  178.         if ( i_end_time != -1 && i_user_time == i_prev_user_time )
  179.         {
  180.             i_user_end_time = i_user_start_time - i_start_time + i_end_time;
  181.         }
  182.         else
  183.         {
  184.             i_user_end_time = i_user_time;
  185.         }
  186.     }
  187.     else
  188.     {
  189.         if ( sub_chapters.begin() != sub_chapters.end() )
  190.             std::sort( sub_chapters.begin(), sub_chapters.end(), chapter_item_c::CompareTimecode );
  191.         i_user_start_time = i_start_time;
  192.         if ( i_end_time != -1 )
  193.             i_user_end_time = i_end_time;
  194.         else if ( i_user_time != -1 )
  195.             i_user_end_time = i_user_time;
  196.         else
  197.             i_user_end_time = i_user_start_time;
  198.     }
  199.     return i_user_end_time;
  200. }
  201. chapter_item_c *chapter_item_c::FindTimecode( mtime_t i_user_timecode, const chapter_item_c * p_current, bool & b_found )
  202. {
  203.     chapter_item_c *psz_result = NULL;
  204.     if ( p_current == this )
  205.         b_found = true;
  206.     if ( i_user_timecode >= i_user_start_time &&
  207.         ( i_user_timecode < i_user_end_time ||
  208.           ( i_user_start_time == i_user_end_time && i_user_timecode == i_user_end_time )))
  209.     {
  210.         std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
  211.         while ( index != sub_chapters.end() && ((p_current == NULL && psz_result == NULL) || (p_current != NULL && (!b_found || psz_result == NULL))))
  212.         {
  213.             psz_result = (*index)->FindTimecode( i_user_timecode, p_current, b_found );
  214.             index++;
  215.         }
  216.  
  217.         if ( psz_result == NULL )
  218.             psz_result = this;
  219.     }
  220.     return psz_result;
  221. }
  222. bool chapter_item_c::ParentOf( const chapter_item_c & item ) const
  223. {
  224.     if ( &item == this )
  225.         return true;
  226.     std::vector<chapter_item_c*>::const_iterator index = sub_chapters.begin();
  227.     while ( index != sub_chapters.end() )
  228.     {
  229.         if ( (*index)->ParentOf( item ) )
  230.             return true;
  231.         index++;
  232.     }
  233.     return false;
  234. }
  235. bool chapter_item_c::Enter( bool b_do_subs )
  236. {
  237.     bool f_result = false;
  238.     std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
  239.     while ( index != codecs.end() )
  240.     {
  241.         f_result |= (*index)->Enter();
  242.         index++;
  243.     }
  244.     if ( b_do_subs )
  245.     {
  246.         // sub chapters
  247.         std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
  248.         while ( index_ != sub_chapters.end() )
  249.         {
  250.             f_result |= (*index_)->Enter( true );
  251.             index_++;
  252.         }
  253.     }
  254.     return f_result;
  255. }
  256. bool chapter_item_c::Leave( bool b_do_subs )
  257. {
  258.     bool f_result = false;
  259.     b_is_leaving = true;
  260.     std::vector<chapter_codec_cmds_c*>::iterator index = codecs.begin();
  261.     while ( index != codecs.end() )
  262.     {
  263.         f_result |= (*index)->Leave();
  264.         index++;
  265.     }
  266.     if ( b_do_subs )
  267.     {
  268.         // sub chapters
  269.         std::vector<chapter_item_c*>::iterator index_ = sub_chapters.begin();
  270.         while ( index_ != sub_chapters.end() )
  271.         {
  272.             f_result |= (*index_)->Leave( true );
  273.             index_++;
  274.         }
  275.     }
  276.     b_is_leaving = false;
  277.     return f_result;
  278. }
  279. bool chapter_item_c::EnterAndLeave( chapter_item_c *p_item, bool b_final_enter )
  280. {
  281.     chapter_item_c *p_common_parent = p_item;
  282.     // leave, up to a common parent
  283.     while ( p_common_parent != NULL && !p_common_parent->ParentOf( *this ) )
  284.     {
  285.         if ( !p_common_parent->b_is_leaving && p_common_parent->Leave( false ) )
  286.             return true;
  287.         p_common_parent = p_common_parent->psz_parent;
  288.     }
  289.     // enter from the parent to <this>
  290.     if ( p_common_parent != NULL )
  291.     {
  292.         do
  293.         {
  294.             if ( p_common_parent == this )
  295.                 return Enter( true );
  296.             for ( size_t i = 0; i<p_common_parent->sub_chapters.size(); i++ )
  297.             {
  298.                 if ( p_common_parent->sub_chapters[i]->ParentOf( *this ) )
  299.                 {
  300.                     p_common_parent = p_common_parent->sub_chapters[i];
  301.                     if ( p_common_parent != this )
  302.                         if ( p_common_parent->Enter( false ) )
  303.                             return true;
  304.                     break;
  305.                 }
  306.             }
  307.         } while ( 1 );
  308.     }
  309.     if ( b_final_enter )
  310.         return Enter( true );
  311.     else
  312.         return false;
  313. }
  314. /* Chapter Edition Class */
  315. std::string chapter_edition_c::GetMainName() const
  316. {
  317.     if ( sub_chapters.size() )
  318.     {
  319.         return sub_chapters[0]->GetCodecName( true );
  320.     }
  321.     return "";
  322. }
  323. void chapter_edition_c::RefreshChapters( )
  324. {
  325.     chapter_item_c::RefreshChapters( b_ordered, -1 );
  326.     b_display_seekpoint = false;
  327. }
  328. mtime_t chapter_edition_c::Duration() const
  329. {
  330.     mtime_t i_result = 0;
  331.  
  332.     if ( sub_chapters.size() )
  333.     {
  334.         std::vector<chapter_item_c*>::const_iterator index = sub_chapters.end();
  335.         index--;
  336.         i_result = (*index)->i_user_end_time;
  337.     }
  338.  
  339.     return i_result;
  340. }
  341. chapter_item_c * chapter_edition_c::FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current )
  342. {
  343.     if ( !b_ordered )
  344.         p_current = NULL;
  345.     bool b_found_current = false;
  346.     return chapter_item_c::FindTimecode( i_timecode, p_current, b_found_current );
  347. }