1 /*****************************************************************************
2  * virtual_segment.hpp : virtual segment implementation in the MKV demuxer
3  *****************************************************************************
4  * Copyright © 2003-2011 VideoLAN and VLC authors
5  * $Id: 53d297f2cb1b8be7a7106840de4c1299497299b9 $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Steve Lhomme <steve.lhomme@free.fr>
9  *          Denis Charmet <typx@dinauz.org>
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25 
26 #ifndef VLC_MKV_VIRTUAL_SEGMENT_HPP_
27 #define VLC_MKV_VIRTUAL_SEGMENT_HPP_
28 
29 #include "mkv.hpp"
30 
31 #include "matroska_segment.hpp"
32 #include "chapters.hpp"
33 
34 /* virtual classes don't own anything but virtual elements so they shouldn't have to delete anything */
35 
36 class virtual_chapter_c
37 {
38 public:
virtual_chapter_c(matroska_segment_c & seg,chapter_item_c * p_chap,int64_t start,int64_t stop,std::vector<virtual_chapter_c * > & sub_chaps)39     virtual_chapter_c( matroska_segment_c &seg, chapter_item_c *p_chap, int64_t start, int64_t stop, std::vector<virtual_chapter_c *> & sub_chaps ):
40         segment(seg), p_chapter(p_chap),
41         i_mk_virtual_start_time(start), i_mk_virtual_stop_time(stop),
42         sub_vchapters(sub_chaps)
43     {}
44     ~virtual_chapter_c();
45 
46     static virtual_chapter_c * CreateVirtualChapter( chapter_item_c * p_chap,
47                                                      matroska_segment_c & main_segment,
48                                                      std::vector<matroska_segment_c*> & segments,
49                                                      int64_t & usertime_offset, bool b_ordered );
50 
51     virtual_chapter_c* getSubChapterbyTimecode( int64_t time );
52     bool Leave( );
53     bool EnterAndLeave( virtual_chapter_c *p_leaving_vchapter, bool b_enter = true );
54     virtual_chapter_c * FindChapter( int64_t i_find_uid );
55     int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level, bool allow_no_name );
56 
57     virtual_chapter_c * BrowseCodecPrivate( unsigned int codec_id,
58                                             bool (*match)( const chapter_codec_cmds_c &data,
59                                                            const void *p_cookie,
60                                                            size_t i_cookie_size ),
61                                             const void *p_cookie,
62                                             size_t i_cookie_size );
63     bool Enter( bool b_do_subs );
64     bool Leave( bool b_do_subs );
65 
CompareTimecode(const virtual_chapter_c * itemA,const virtual_chapter_c * itemB)66     static bool CompareTimecode( const virtual_chapter_c * itemA, const virtual_chapter_c * itemB )
67     {
68         return ( itemA->i_mk_virtual_start_time < itemB->i_mk_virtual_start_time );
69     }
70 
71     bool ContainsTimestamp( mtime_t i_pts );
72 
73     matroska_segment_c  &segment;
74     chapter_item_c      *p_chapter;
75     mtime_t             i_mk_virtual_start_time;
76     mtime_t             i_mk_virtual_stop_time;
77     int                 i_seekpoint_num;
78     std::vector<virtual_chapter_c *> sub_vchapters;
79 #ifdef MKV_DEBUG
80     void print();
81 #endif
82 };
83 
84 class virtual_edition_c
85 {
86 public:
87     virtual_edition_c( chapter_edition_c * p_edition, matroska_segment_c & main_segment, std::vector<matroska_segment_c*> & opened_segments );
88     ~virtual_edition_c();
89     std::vector<virtual_chapter_c*> vchapters;
90 
91     virtual_chapter_c* getChapterbyTimecode( int64_t time );
92     std::string GetMainName();
93     int PublishChapters( input_title_t & title, int & i_user_chapters, int i_level );
94     virtual_chapter_c * BrowseCodecPrivate( unsigned int codec_id,
95                                             bool (*match)( const chapter_codec_cmds_c &data,
96                                                            const void *p_cookie,
97                                                            size_t i_cookie_size ),
98                                              const void *p_cookie, size_t i_cookie_size );
99 
100     bool                b_ordered;
101     mtime_t             i_duration;
102     chapter_edition_c   *p_edition;
103     int                 i_seekpoint_num;
104 
105 private:
106     void retimeChapters();
107     void retimeSubChapters( virtual_chapter_c * p_vchap );
108 #ifdef MKV_DEBUG
print()109     void print(){ for( size_t i = 0; i<chapters.size(); i++ ) chapters[i]->print(); }
110 #endif
111 
112 };
113 
114 // class holding hard-linked segment together in the playback order
115 class virtual_segment_c
116 {
117 public:
118     virtual_segment_c( matroska_segment_c & segment, std::vector<matroska_segment_c*> & opened_segments );
119     ~virtual_segment_c();
120     std::vector<virtual_edition_c*> veditions;
121     std::vector<virtual_edition_c*>::size_type i_current_edition;
122     virtual_chapter_c               *p_current_vchapter;
123     bool                            b_current_vchapter_entered;
124     int                             i_sys_title;
125 
126 
CurrentEdition()127     inline virtual_edition_c * CurrentEdition()
128     {
129         if( i_current_edition < veditions.size() )
130             return veditions[i_current_edition];
131         return NULL;
132     }
133 
CurrentChapter() const134     virtual_chapter_c * CurrentChapter() const
135     {
136         return p_current_vchapter;
137     }
138 
CurrentSegment() const139     matroska_segment_c * CurrentSegment() const
140     {
141         if ( !p_current_vchapter )
142             return NULL;
143         return &p_current_vchapter->segment;
144     }
145 
Duration()146     inline int64_t Duration()
147     {
148         return veditions[i_current_edition]->i_duration / 1000;
149     }
150 
Editions()151     inline std::vector<virtual_edition_c*>* Editions() { return &veditions; }
152 
153     virtual_chapter_c *BrowseCodecPrivate( unsigned int codec_id,
154                                            bool (*match)( const chapter_codec_cmds_c &data,
155                                                           const void *p_cookie,
156                                                           size_t i_cookie_size ),
157                                            const void *p_cookie,
158                                            size_t i_cookie_size );
159 
160     virtual_chapter_c * FindChapter( int64_t i_find_uid );
161 
162     bool UpdateCurrentToChapter( demux_t & demux );
163     bool Seek( demux_t & demuxer, mtime_t i_mk_date, virtual_chapter_c *p_vchapter, bool b_precise = true );
164 private:
165     void KeepTrackSelection( matroska_segment_c & old, matroska_segment_c & next );
166 };
167 
168 #endif
169