]> git.sesse.net Git - vlc/blob - modules/demux/mkv/virtual_segment.cpp
msg: simplify msg_GenericVa() macro
[vlc] / modules / demux / mkv / virtual_segment.cpp
1 /*****************************************************************************
2  * virtual_segment.cpp : virtual segment implementation in the MKV demuxer
3  *****************************************************************************
4  * Copyright © 2003-2011 VideoLAN and VLC authors
5  * $Id$
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 #include <vector>
26
27 #include "demux.hpp"
28
29 /* FIXME move this */
30 matroska_segment_c * getSegmentbyUID( KaxSegmentUID * p_uid, std::vector<matroska_segment_c*> *segments )
31 {
32     for( size_t i = 0; i < (*segments).size(); i++ )
33     {
34         if( (*segments)[i]->p_segment_uid &&
35             *p_uid == *((*segments)[i]->p_segment_uid) )
36             return (*segments)[i];
37     }
38     return NULL;
39 }
40
41 virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_chap,
42                                                              matroska_segment_c * p_main_segment,
43                                                              std::vector<matroska_segment_c*> * segments,
44                                                              int64_t * usertime_offset, bool b_ordered)
45 {
46     matroska_segment_c * p_segment = p_main_segment;
47
48     if( !p_chap )
49     {
50         /* Dummy chapter use the whole segment */
51         return new virtual_chapter_c( p_segment, NULL, 0, p_segment->i_duration*1000 );
52     }
53
54     int64_t start = ( b_ordered )? *usertime_offset : p_chap->i_start_time;
55     int64_t stop = ( b_ordered )? ( *usertime_offset + p_chap->i_end_time - p_chap->i_start_time ) : p_chap->i_end_time;
56
57     if( p_chap->p_segment_uid &&
58        ( !( p_segment = getSegmentbyUID( (KaxSegmentUID*) p_chap->p_segment_uid,segments ) ) || !b_ordered ) )
59     {
60         msg_Warn( &p_main_segment->sys.demuxer,
61                   "Couldn't find segment 0x%x or not ordered... - ignoring chapter %s",
62                   *( (uint32_t *) p_chap->p_segment_uid->GetBuffer() ),p_chap->psz_name.c_str() );
63         return NULL;
64     }
65
66     /* Preload segment */
67     if ( !p_segment->b_preloaded )
68         p_segment->Preload();
69
70     virtual_chapter_c * p_vchap = new virtual_chapter_c( p_segment, p_chap, start, stop );
71
72     if( !p_vchap )
73         return NULL;
74
75     int64_t tmp = *usertime_offset;
76
77     for( size_t i = 0; i < p_chap->sub_chapters.size(); i++ )
78     {
79         virtual_chapter_c * p_vsubchap = CreateVirtualChapter( p_chap->sub_chapters[i], p_segment, segments, &tmp, b_ordered );
80
81         if( p_vsubchap )
82             p_vchap->sub_chapters.push_back( p_vsubchap );
83     }
84
85     if( tmp == *usertime_offset )
86         *usertime_offset += p_chap->i_end_time - p_chap->i_start_time;
87     else
88         *usertime_offset = tmp;
89
90     msg_Dbg( &p_main_segment->sys.demuxer,
91              "Virtual chapter %s from %" PRId64 " to %" PRId64 " - " ,
92              p_chap->psz_name.c_str(), p_vchap->i_virtual_start_time, p_vchap->i_virtual_stop_time );
93
94     return p_vchap;
95 }
96
97 virtual_chapter_c::~virtual_chapter_c()
98 {
99     for( size_t i = 0 ; i < sub_chapters.size(); i++ )
100         delete sub_chapters[i];
101 }
102
103
104 virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<matroska_segment_c*> *opened_segments)
105 {
106     bool b_fake_ordered = false;
107     matroska_segment_c *p_main_segment = (*opened_segments)[0];
108     p_edition = p_edit;
109     b_ordered = false;
110
111     int64_t usertime_offset = 0;
112
113     /* ordered chapters */
114     if( p_edition && p_edition->b_ordered )
115     {
116         b_ordered = true;
117         for( size_t i = 0; i < p_edition->sub_chapters.size(); i++ )
118         {
119             virtual_chapter_c * p_vchap = virtual_chapter_c::CreateVirtualChapter( p_edition->sub_chapters[i],
120                                                                                    p_main_segment, opened_segments,
121                                                                                    &usertime_offset, b_ordered );
122             if( p_vchap )
123                 chapters.push_back( p_vchap );
124         }
125         if( chapters.size() )
126             i_duration = chapters[ chapters.size() - 1 ]->i_virtual_stop_time;
127         else
128             i_duration = 0; /* Empty ordered editions will be ignored */
129     }
130     else /* Not ordered or no edition at all */
131     {
132         matroska_segment_c * p_cur = p_main_segment;
133         virtual_chapter_c * p_vchap = NULL;
134         int64_t tmp = 0;
135
136         /* check for prev linked segments */
137         /* FIXME to avoid infinite recursion we limit to 10 prev should be better as parameter */
138         for( int limit = 0; limit < 10 && p_cur->p_prev_segment_uid ; limit++ )
139         {
140             matroska_segment_c * p_prev = NULL;
141             if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) )
142             {
143                 tmp = 0;
144                 msg_Dbg( &p_main_segment->sys.demuxer, "Prev segment 0x%x found\n",
145                          *(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() );
146
147                 /* Preload segment */
148                 if ( !p_prev->b_preloaded )
149                     p_prev->Preload();
150
151                 /* Create virtual_chapter from the first edition if any */
152                 chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL;
153
154                 p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_prev, opened_segments, &tmp, b_ordered );
155
156                 if( p_vchap )
157                     chapters.insert( chapters.begin(), p_vchap );
158
159                 p_cur = p_prev;
160                 b_fake_ordered = true;
161             }
162             else /* segment not found */
163                 break;
164         }
165
166         tmp = 0;
167
168         /* Append the main segment */
169         p_vchap = virtual_chapter_c::CreateVirtualChapter( (chapter_item_c*) p_edit, p_main_segment,
170                                                            opened_segments, &tmp, b_ordered );
171         if( p_vchap )
172             chapters.push_back( p_vchap );
173
174         /* Append next linked segments */
175         for( int limit = 0; limit < 10 && p_cur->p_next_segment_uid; limit++ )
176         {
177             matroska_segment_c * p_next = NULL;
178             if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) )
179             {
180                 tmp = 0;
181                 msg_Dbg( &p_main_segment->sys.demuxer, "Next segment 0x%x found\n",
182                          *(int32_t*) p_cur->p_next_segment_uid->GetBuffer() );
183
184                 /* Preload segment */
185                 if ( !p_next->b_preloaded )
186                     p_next->Preload();
187
188                 /* Create virtual_chapter from the first edition if any */
189                 chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL;
190
191                  p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_next, opened_segments, &tmp, b_ordered );
192
193                 if( p_vchap )
194                     chapters.push_back( p_vchap );
195
196
197                 p_cur = p_next;
198                 b_fake_ordered = true;
199             }
200             else /* segment not found */
201                 break;
202         }
203
204         /* Retime chapters */
205         retimeChapters();
206         if(b_fake_ordered)
207             b_ordered = true;
208     }
209
210 #if MKV_DEBUG
211     msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-BEGIN --" );
212     print();
213     msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-END --" );
214 #endif
215 }
216
217 virtual_edition_c::~virtual_edition_c()
218 {
219     for( size_t i = 0; i < chapters.size(); i++ )
220         delete chapters[i];
221 }
222
223 void virtual_edition_c::retimeSubChapters( virtual_chapter_c * p_vchap )
224 {
225     int64_t stop_time = p_vchap->i_virtual_stop_time;
226     for( size_t i = p_vchap->sub_chapters.size(); i-- > 0; )
227     {
228         virtual_chapter_c * p_vsubchap = p_vchap->sub_chapters[i];
229         p_vsubchap->i_virtual_start_time += p_vchap->i_virtual_start_time;
230
231         /*FIXME we artificially extend stop time if they were there before...*/
232         /* Just for comfort*/
233         p_vsubchap->i_virtual_stop_time = stop_time;
234         stop_time = p_vsubchap->i_virtual_start_time;
235
236         retimeSubChapters( p_vsubchap );
237     }
238 }
239
240 void virtual_edition_c::retimeChapters()
241 {
242     /* This function is just meant to be used on unordered chapters */
243     if( b_ordered )
244         return;
245
246     i_duration = 0;
247
248     /* On non ordered editions we have one top chapter == one segment */
249     for( size_t i = 0; i < chapters.size(); i++ )
250     {
251         virtual_chapter_c * p_vchap = chapters[i];
252
253         p_vchap->i_virtual_start_time = i_duration;
254         i_duration += p_vchap->p_segment->i_duration * 1000;
255         p_vchap->i_virtual_stop_time = i_duration;
256
257         retimeSubChapters( p_vchap );
258     }
259 }
260
261 virtual_segment_c::virtual_segment_c( std::vector<matroska_segment_c*> * p_opened_segments )
262 {
263     /* Main segment */
264     std::vector<chapter_edition_c*>::size_type i;
265     matroska_segment_c *p_segment = (*p_opened_segments)[0];
266     i_current_edition = 0;
267     i_sys_title = 0;
268     p_current_chapter = NULL;
269
270     i_current_edition = p_segment->i_default_edition;
271
272     for( i = 0; i < p_segment->stored_editions.size(); i++ )
273     {
274         /* Create a virtual edition from opened */
275         virtual_edition_c * p_vedition = new virtual_edition_c( p_segment->stored_editions[i], p_opened_segments );
276
277         /* Ordered empty edition can happen when all chapters are
278          * on an other segment which couldn't be found... ignore it */
279         if(p_vedition->b_ordered && p_vedition->i_duration == 0)
280         {
281
282             msg_Warn( &p_segment->sys.demuxer,
283                       "Edition %s (%zu) links to other segments not found and is empty... ignoring it",
284                        p_vedition->GetMainName().c_str(), i );
285             if(i_current_edition == i)
286             {
287                 msg_Warn( &p_segment->sys.demuxer,
288                           "Empty edition was the default... defaulting to 0");
289                 i_current_edition = 0;
290             }
291             delete p_vedition;
292         }
293         else
294             editions.push_back( p_vedition );
295     }
296     /*if we don't have edition create a dummy one*/
297     if( !p_segment->stored_editions.size() )
298     {
299         virtual_edition_c * p_vedition = new virtual_edition_c( NULL, p_opened_segments );
300         editions.push_back( p_vedition );
301     }
302
303     /* Get the default edition, if there is none, use the first one */
304     for( i = 0; i < editions.size(); i++)
305     {
306         if( editions[i]->p_edition && editions[i]->p_edition->b_default )
307         {
308             i_current_edition = i;
309             break;
310         }
311     }
312     /* Set current chapter */
313     p_current_chapter = editions[i_current_edition]->getChapterbyTimecode(0);
314
315 }
316
317 virtual_segment_c::~virtual_segment_c()
318 {
319     for( size_t i = 0; i < editions.size(); i++ )
320         delete editions[i];
321 }
322
323 virtual_chapter_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
324                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
325                                     const void *p_cookie,
326                                     size_t i_cookie_size )
327 {
328     virtual_edition_c * p_ved = CurrentEdition();
329     if( p_ved )
330         return p_ved->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
331
332     return NULL;
333 }
334
335
336 virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( unsigned int codec_id,
337                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
338                                     const void *p_cookie,
339                                     size_t i_cookie_size )
340 {
341     if( !p_edition )
342         return NULL;
343
344     for( size_t i = 0; i < chapters.size(); i++ )
345     {
346         virtual_chapter_c * p_result = chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
347         if( p_result )
348             return p_result;
349     }
350     return NULL;
351 }
352
353
354
355 virtual_chapter_c * virtual_chapter_c::BrowseCodecPrivate( unsigned int codec_id,
356                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
357                                     const void *p_cookie,
358                                     size_t i_cookie_size )
359 {
360     if( !p_chapter )
361         return NULL;
362
363     if( p_chapter->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size ) )
364         return this;
365
366     for( size_t i = 0; i < sub_chapters.size(); i++ )
367     {
368         virtual_chapter_c * p_result = sub_chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
369         if( p_result )
370             return p_result;
371     }
372     return NULL;
373 }
374
375 virtual_chapter_c* virtual_chapter_c::getSubChapterbyTimecode( int64_t time )
376 {
377     for( size_t i = 0; i < sub_chapters.size(); i++ )
378     {
379         if( time >= sub_chapters[i]->i_virtual_start_time && time < sub_chapters[i]->i_virtual_stop_time )
380             return sub_chapters[i]->getSubChapterbyTimecode( time );
381     }
382
383     return this;
384 }
385
386 virtual_chapter_c* virtual_edition_c::getChapterbyTimecode( int64_t time )
387 {
388     for( size_t i = 0; i < chapters.size(); i++ )
389     {
390         if( time >= chapters[i]->i_virtual_start_time &&
391             ( chapters[i]->i_virtual_stop_time < 0 || time < chapters[i]->i_virtual_stop_time ) )
392             /*with the current implementation only the last chapter can have a negative virtual_stop_time*/
393             return chapters[i]->getSubChapterbyTimecode( time );
394     }
395
396     return NULL;
397 }
398
399 bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
400 {
401     demux_sys_t & sys = *demux.p_sys;
402     virtual_chapter_c *p_cur_chapter;
403     virtual_edition_c * p_cur_edition = editions[ i_current_edition ];
404
405     bool b_has_seeked = false;
406
407     p_cur_chapter = p_cur_edition->getChapterbyTimecode( sys.i_pts );
408
409     /* we have moved to a new chapter */
410     if ( p_cur_chapter != NULL && p_current_chapter != p_cur_chapter )
411         {
412             msg_Dbg( &demux, "NEW CHAPTER %" PRId64, sys.i_pts );
413             if ( p_cur_edition->b_ordered )
414             {
415                 /* FIXME EnterAndLeave has probably been broken for a long time */
416                 // Leave/Enter up to the link point
417                 b_has_seeked = p_cur_chapter->EnterAndLeave( p_current_chapter );
418                 if ( !b_has_seeked )
419                 {
420                     // only physically seek if necessary
421                     if ( p_current_chapter == NULL ||
422                         ( p_current_chapter && p_current_chapter->p_segment != p_cur_chapter->p_segment ) ||
423                         ( p_current_chapter->p_chapter->i_end_time != p_cur_chapter->p_chapter->i_start_time ))
424                     {
425                         Seek( demux, p_cur_chapter->i_virtual_start_time, 0, p_cur_chapter, -1 );
426                         return true;
427                     }
428                 }
429                 sys.i_start_pts = p_cur_chapter->i_virtual_start_time;;
430             }
431
432             p_current_chapter = p_cur_chapter;
433             if ( p_cur_chapter->i_seekpoint_num > 0 )
434             {
435                 demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
436                 demux.info.i_title = sys.i_current_title = i_sys_title;
437                 demux.info.i_seekpoint = p_cur_chapter->i_seekpoint_num - 1;
438             }
439
440             return b_has_seeked;
441         }
442         else if ( p_cur_chapter == NULL )
443         {
444             /* out of the scope of the data described by chapters, leave the edition */
445             if ( p_cur_edition->b_ordered && p_current_chapter != NULL )
446             {
447                 /* TODO */
448                 if ( !p_cur_edition->p_edition->EnterAndLeave( p_current_chapter->p_chapter, false ) )
449                     p_current_chapter = NULL;
450                 else
451                     return true;
452             }
453         }
454     return false;
455 }
456
457 bool virtual_chapter_c::EnterAndLeave( virtual_chapter_c *p_item, bool b_enter )
458 {
459     if( !p_chapter )
460         return false;
461
462     return p_chapter->EnterAndLeave( p_item->p_chapter, b_enter );
463 }
464
465 void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset,
466                               virtual_chapter_c *p_chapter, int64_t i_global_position )
467 {
468     demux_sys_t *p_sys = demuxer.p_sys;
469
470
471     /* find the actual time for an ordered edition */
472     if ( p_chapter == NULL )
473         /* 1st, we need to know in which chapter we are */
474         p_chapter = editions[ i_current_edition ]->getChapterbyTimecode( i_date );
475
476     if ( p_chapter != NULL )
477     {
478         i_time_offset = p_chapter->i_virtual_start_time - ( ( p_chapter->p_chapter )? p_chapter->p_chapter->i_start_time : 0 );
479         p_sys->i_chapter_time = i_time_offset - p_chapter->p_segment->i_start_time;
480         if ( p_chapter->p_chapter && p_chapter->i_seekpoint_num > 0 )
481         {
482             demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
483             demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
484             demuxer.info.i_seekpoint = p_chapter->i_seekpoint_num - 1;
485         }
486
487         if( p_current_chapter->p_segment != p_chapter->p_segment )
488             ChangeSegment( p_current_chapter->p_segment, p_chapter->p_segment, i_date );
489         p_current_chapter = p_chapter;
490
491         p_chapter->p_segment->Seek( i_date, i_time_offset, i_global_position );
492     }
493 }
494
495 virtual_chapter_c * virtual_chapter_c::FindChapter( int64_t i_find_uid )
496 {
497     if( p_chapter && ( p_chapter->i_uid == i_find_uid ) )
498         return this;
499
500     for( size_t i = 0; i < sub_chapters.size(); i++ )
501     {
502         virtual_chapter_c * p_res = sub_chapters[i]->FindChapter( i_find_uid );
503         if( p_res )
504             return p_res;
505     }
506
507     return NULL;
508 }
509
510 virtual_chapter_c * virtual_segment_c::FindChapter( int64_t i_find_uid )
511 {
512     virtual_edition_c * p_edition = editions[i_current_edition];
513
514     for( size_t i = 0; p_edition->chapters.size(); i++ )
515     {
516         virtual_chapter_c * p_chapter = p_edition->chapters[i]->FindChapter( i_find_uid );
517         if( p_chapter )
518             return p_chapter;
519     }
520     return NULL;
521 }
522
523 int virtual_chapter_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
524 {
525     if ( p_chapter && ( !p_chapter->b_display_seekpoint || p_chapter->psz_name == "" ) )
526     {
527         p_chapter->psz_name = p_chapter->GetCodecName();
528         if ( p_chapter->psz_name != "" )
529             p_chapter->b_display_seekpoint = true;
530     }
531
532     if ( ( p_chapter && p_chapter->b_display_seekpoint &&
533          ( ( sub_chapters.size() > 0 && i_virtual_start_time != sub_chapters[0]->i_virtual_start_time) ||
534            sub_chapters.size() == 0 ) ) || !p_chapter )
535     {
536         seekpoint_t *sk = vlc_seekpoint_New();
537
538         sk->i_time_offset = i_virtual_start_time;
539         if( p_chapter )
540             sk->psz_name = strdup( p_chapter->psz_name.c_str() );
541         else
542             sk->psz_name = strdup("dummy chapter");
543
544         /* A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value. */
545         title.i_seekpoint++;
546         title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
547                                  title.i_seekpoint * sizeof( seekpoint_t* ) );
548         title.seekpoint[title.i_seekpoint-1] = sk;
549
550         if ( (p_chapter && p_chapter->b_user_display ) ||  !p_chapter )
551             i_user_chapters++;
552     }
553     i_seekpoint_num = i_user_chapters;
554
555     for( size_t i = 0; i < sub_chapters.size(); i++ )
556         sub_chapters[i]->PublishChapters( title, i_user_chapters, i_level + 1 );
557
558     return i_user_chapters;
559 }
560
561
562 int virtual_edition_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
563 {
564
565     /* HACK for now don't expose edition as a seekpoint if its start time is the same than it's first chapter */
566     if( chapters.size() > 0 &&
567         chapters[0]->i_virtual_start_time && p_edition )
568     {
569         seekpoint_t *sk = vlc_seekpoint_New();
570
571         sk->i_time_offset = 0;
572         sk->psz_name = strdup( p_edition->psz_name.c_str() );
573
574         title.i_seekpoint++;
575         title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
576                              title.i_seekpoint * sizeof( seekpoint_t* ) );
577         title.seekpoint[title.i_seekpoint - 1] = sk;
578         i_level++;
579
580         i_user_chapters++;
581         i_seekpoint_num = i_user_chapters;
582     }
583
584 //    if( chapters.size() > 1 )
585         for( size_t i = 0; i < chapters.size(); i++ )
586             chapters[i]->PublishChapters( title, i_user_chapters, i_level );
587
588     return i_user_chapters;
589 }
590
591 std::string virtual_edition_c::GetMainName()
592 {
593     if( p_edition )
594         return p_edition->GetMainName();
595
596     return std::string("");
597 }
598
599 bool virtual_chapter_c::Enter( bool b_do_subs )
600 {
601     if( p_chapter )
602         return p_chapter->Enter( b_do_subs );
603     return false;
604 }
605
606 bool virtual_chapter_c::Leave( bool b_do_subs )
607 {
608     if( p_chapter )
609         return p_chapter->Leave( b_do_subs );
610     return false;
611 }
612
613 #if MKV_DEBUG
614 void virtual_chapter_c::print()
615 {
616     msg_Dbg( &p_segment->sys.demuxer, "*** chapter %"PRId64" - %"PRId64" (%u)",
617              i_virtual_start_time, i_virtual_stop_time, sub_chapters.size() );
618     for( size_t i = 0; i < sub_chapters.size(); i++ )
619         sub_chapters[i]->print();
620 }
621 #endif
622
623 void virtual_segment_c::ChangeSegment( matroska_segment_c * p_old, matroska_segment_c * p_new, mtime_t i_start_time )
624 {
625     size_t i, j;
626     char *sub_lang = NULL, *aud_lang = NULL;
627     for( i = 0; i < p_old->tracks.size(); i++)
628     {
629         mkv_track_t *p_tk = p_old->tracks[i];
630         es_format_t *p_ofmt = &p_tk->fmt;
631         if( p_tk->p_es )
632         {
633             bool state = false;
634             es_out_Control( p_old->sys.demuxer.out, ES_OUT_GET_ES_STATE, p_tk->p_es, &state );
635             if( state )
636             {
637                 if( p_ofmt->i_cat == AUDIO_ES )
638                     aud_lang = p_tk->fmt.psz_language;
639                 else if( p_ofmt->i_cat == SPU_ES )
640                     sub_lang = p_tk->fmt.psz_language;
641             }
642         }
643     }
644     for( i = 0; i < p_new->tracks.size(); i++)
645     {
646         mkv_track_t *p_tk = p_new->tracks[i];
647         es_format_t *p_nfmt = &p_tk->fmt;
648
649         /* Let's only do that for audio and video for now */
650         if( p_nfmt->i_cat == AUDIO_ES || p_nfmt->i_cat == VIDEO_ES )
651         {
652
653             /* check for a similar elementary stream */
654             for( j = 0; j < p_old->tracks.size(); j++)
655             {
656                 es_format_t * p_ofmt = &p_old->tracks[j]->fmt;
657
658                 if( !p_old->tracks[j]->p_es )
659                     continue;
660
661                 if( ( p_nfmt->i_cat == p_ofmt->i_cat ) &&
662                     ( p_nfmt->i_codec == p_ofmt->i_codec ) &&
663                     ( p_nfmt->i_priority == p_ofmt->i_priority ) &&
664                     ( p_nfmt->i_bitrate == p_ofmt->i_bitrate ) &&
665                     ( p_nfmt->i_extra == p_ofmt->i_extra ) &&
666                     ( p_nfmt->i_extra == 0 ||
667                       !memcmp( p_nfmt->p_extra, p_ofmt->p_extra, p_nfmt->i_extra ) ) &&
668                     !strcasecmp( p_nfmt->psz_language, p_ofmt->psz_language ) &&
669                     ( ( p_nfmt->i_cat == AUDIO_ES &&
670                         !memcmp( &p_nfmt->audio, &p_ofmt->audio, sizeof(audio_format_t) ) ) ||
671                       ( p_nfmt->i_cat == VIDEO_ES &&
672                         !memcmp( &p_nfmt->video, &p_ofmt->video, sizeof(video_format_t) ) ) ) )
673                 {
674                     /* FIXME handle video palettes... */
675                     msg_Warn( &p_old->sys.demuxer, "Reusing decoder of old track %zu for track %zu", j, i);
676                     p_tk->p_es = p_old->tracks[j]->p_es;
677                     p_old->tracks[j]->p_es = NULL;
678                     break;
679                 }
680             }
681         }
682         p_tk->fmt.i_priority &= ~(0x10);
683         if( ( sub_lang && p_nfmt->i_cat == SPU_ES && !strcasecmp(sub_lang, p_nfmt->psz_language) ) ||
684             ( aud_lang && p_nfmt->i_cat == AUDIO_ES && !strcasecmp(aud_lang, p_nfmt->psz_language) ) )
685         {
686             msg_Warn( &p_old->sys.demuxer, "Since previous segment used lang %s forcing track %zu",
687                       p_nfmt->psz_language, i);
688             p_tk->fmt.i_priority |= 0x10;
689             p_tk->b_forced = true;
690         }
691     }
692     p_new->Select( i_start_time );
693     p_old->UnSelect();
694 }