1 /*****************************************************************************
2 * mkv.cpp : matroska demuxer
3 *****************************************************************************
4 * Copyright (C) 2003-2004 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Steve Lhomme <steve.lhomme@free.fr>
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.
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.
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 *****************************************************************************/
25 #include "virtual_segment.hpp"
29 void virtual_segment_c::PrepareChapters( )
31 if ( linked_segments.size() == 0 )
34 // !!! should be called only once !!!
35 matroska_segment_c *p_segment;
37 // copy editions from the first segment
38 p_segment = linked_segments[0];
39 p_editions = &p_segment->stored_editions;
41 for ( size_t i=1 ; i<linked_segments.size(); i++ )
43 p_segment = linked_segments[i];
44 // FIXME assume we have the same editions in all segments
45 for ( size_t j=0; j<p_segment->stored_editions.size(); j++)
47 if( j >= p_editions->size() ) /* Protect against broken files (?) */
49 (*p_editions)[j]->Append( *p_segment->stored_editions[j] );
54 bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
56 demux_sys_t & sys = *demux.p_sys;
57 chapter_item_c *psz_curr_chapter;
58 bool b_has_seeked = false;
60 /* update current chapter/seekpoint */
61 if ( p_editions->size() )
63 /* 1st, we need to know in which chapter we are */
64 psz_curr_chapter = (*p_editions)[i_current_edition]->FindTimecode( sys.i_pts, psz_current_chapter );
66 /* we have moved to a new chapter */
67 if (psz_curr_chapter != NULL && psz_current_chapter != psz_curr_chapter)
69 if ( (*p_editions)[i_current_edition]->b_ordered )
71 // Leave/Enter up to the link point
72 b_has_seeked = psz_curr_chapter->EnterAndLeave( psz_current_chapter );
75 // only physically seek if necessary
76 if ( psz_current_chapter == NULL || (psz_current_chapter->i_end_time != psz_curr_chapter->i_start_time) )
77 Seek( demux, sys.i_pts, 0, psz_curr_chapter, -1 );
83 psz_current_chapter = psz_curr_chapter;
84 if ( psz_curr_chapter->i_seekpoint_num > 0 )
86 demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
87 demux.info.i_title = sys.i_current_title = i_sys_title;
88 demux.info.i_seekpoint = psz_curr_chapter->i_seekpoint_num - 1;
94 else if (psz_curr_chapter == NULL)
96 // out of the scope of the data described by chapters, leave the edition
97 if ( (*p_editions)[i_current_edition]->b_ordered && psz_current_chapter != NULL )
99 if ( !(*p_editions)[i_current_edition]->EnterAndLeave( psz_current_chapter, false ) )
100 psz_current_chapter = NULL;
109 chapter_item_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
110 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
111 const void *p_cookie,
112 size_t i_cookie_size )
114 // FIXME don't assume it is the first edition
115 std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
116 if ( index != p_editions->end() )
118 chapter_item_c *p_result = (*index)->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
119 if ( p_result != NULL )
126 void virtual_segment_c::Sort()
128 // keep the current segment index
129 matroska_segment_c *p_segment = linked_segments[i_current_segment];
131 std::sort( linked_segments.begin(), linked_segments.end(), matroska_segment_c::CompareSegmentUIDs );
133 for ( i_current_segment=0; i_current_segment<linked_segments.size(); i_current_segment++)
134 if ( linked_segments[i_current_segment] == p_segment )
138 size_t virtual_segment_c::AddSegment( matroska_segment_c *p_segment )
141 // check if it's not already in here
142 for ( i=0; i<linked_segments.size(); i++ )
144 if ( linked_segments[i]->p_segment_uid != NULL
145 && p_segment->p_segment_uid != NULL
146 && *p_segment->p_segment_uid == *linked_segments[i]->p_segment_uid )
150 // find possible mates
151 for ( i=0; i<linked_uids.size(); i++ )
153 if ( (p_segment->p_segment_uid != NULL && *p_segment->p_segment_uid == linked_uids[i])
154 || (p_segment->p_prev_segment_uid != NULL && *p_segment->p_prev_segment_uid == linked_uids[i])
155 || (p_segment->p_next_segment_uid !=NULL && *p_segment->p_next_segment_uid == linked_uids[i]) )
157 linked_segments.push_back( p_segment );
159 AppendUID( p_segment->p_prev_segment_uid );
160 AppendUID( p_segment->p_next_segment_uid );
168 void virtual_segment_c::PreloadLinked( )
170 for ( size_t i=0; i<linked_segments.size(); i++ )
172 linked_segments[i]->Preload( );
174 i_current_edition = linked_segments[0]->i_default_edition;
177 mtime_t virtual_segment_c::Duration() const
180 if ( linked_segments.size() == 0 )
183 matroska_segment_c *p_last_segment = linked_segments[linked_segments.size()-1];
184 // p_last_segment->ParseCluster( );
186 i_duration = p_last_segment->i_start_time / 1000 + p_last_segment->i_duration;
191 void virtual_segment_c::AppendUID( const EbmlBinary * p_UID )
195 if ( p_UID->GetBuffer() == NULL )
198 for (size_t i=0; i<linked_uids.size(); i++)
200 if ( *p_UID == linked_uids[i] )
203 linked_uids.push_back( *(KaxSegmentUID*)(p_UID) );
206 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 )
208 demux_sys_t *p_sys = demuxer.p_sys;
211 // find the actual time for an ordered edition
212 if ( psz_chapter == NULL )
214 if ( Edition() && Edition()->b_ordered )
216 /* 1st, we need to know in which chapter we are */
217 psz_chapter = (*p_editions)[i_current_edition]->FindTimecode( i_date, psz_current_chapter );
221 if ( psz_chapter != NULL )
223 psz_current_chapter = psz_chapter;
224 p_sys->i_chapter_time = i_time_offset = psz_chapter->i_user_start_time - psz_chapter->i_start_time;
225 if ( psz_chapter->i_seekpoint_num > 0 )
227 demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
228 demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
229 demuxer.info.i_seekpoint = psz_chapter->i_seekpoint_num - 1;
233 // find the best matching segment
234 for ( i=0; i<linked_segments.size(); i++ )
236 if ( i_date < linked_segments[i]->i_start_time )
243 if ( i_current_segment != i )
245 linked_segments[i_current_segment]->UnSelect();
246 linked_segments[i]->Select( i_date );
247 i_current_segment = i;
250 linked_segments[i]->Seek( i_date, i_time_offset, i_global_position );
253 chapter_item_c *virtual_segment_c::FindChapter( int64_t i_find_uid )
255 // FIXME don't assume it is the first edition
256 std::vector<chapter_edition_c*>::iterator index = p_editions->begin();
257 if ( index != p_editions->end() )
259 chapter_item_c *p_result = (*index)->FindChapter( i_find_uid );
260 if ( p_result != NULL )