]> git.sesse.net Git - vlc/blob - modules/demux/mkv/virtual_segment.cpp
macosx vout: small cleanup
[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
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 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 General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, 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         i_duration = chapters[ chapters.size() - 1 ]->i_virtual_stop_time;
126     }
127     else /* Not ordered or no edition at all */
128     {
129         matroska_segment_c * p_cur = p_main_segment;
130         virtual_chapter_c * p_vchap = NULL;
131         int64_t tmp = 0;
132
133         /* check for prev linked segments */
134         /* FIXME to avoid infinite recursion we limit to 10 prev should be better as parameter */
135         for( int limit = 0; limit < 10 && p_cur->p_prev_segment_uid ; limit++ )
136         {
137             matroska_segment_c * p_prev = NULL;
138             if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) )
139             {
140                 tmp = 0;
141                 msg_Dbg( &p_main_segment->sys.demuxer, "Prev segment 0x%x found\n",
142                          *(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() );
143
144                 /* Preload segment */
145                 if ( !p_prev->b_preloaded )
146                     p_prev->Preload();
147
148                 /* Create virtual_chapter from the first edition if any */
149                 chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL;
150
151                 p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_prev, opened_segments, &tmp, b_ordered );
152
153                 if( p_vchap )
154                     chapters.insert( chapters.begin(), p_vchap );
155
156                 p_cur = p_prev;
157                 b_fake_ordered = true;
158             }
159             else /* segment not found */
160                 break;
161         }
162
163         tmp = 0;
164
165         /* Append the main segment */
166         p_vchap = virtual_chapter_c::CreateVirtualChapter( (chapter_item_c*) p_edit, p_main_segment,
167                                                            opened_segments, &tmp, b_ordered );
168         if( p_vchap )
169             chapters.push_back( p_vchap );
170
171         /* Append next linked segments */
172         for( int limit = 0; limit < 10 && p_cur->p_next_segment_uid; limit++ )
173         {
174             matroska_segment_c * p_next = NULL;
175             if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) )
176             {
177                 tmp = 0;
178                 msg_Dbg( &p_main_segment->sys.demuxer, "Next segment 0x%x found\n",
179                          *(int32_t*) p_cur->p_next_segment_uid->GetBuffer() );
180
181                 /* Preload segment */
182                 if ( !p_next->b_preloaded )
183                     p_next->Preload();
184
185                 /* Create virtual_chapter from the first edition if any */
186                 chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL;
187
188                  p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_next, opened_segments, &tmp, b_ordered );
189
190                 if( p_vchap )
191                     chapters.push_back( p_vchap );
192
193
194                 p_cur = p_next;
195                 b_fake_ordered = true;
196             }
197             else /* segment not found */
198                 break;
199         }
200
201         /* Retime chapters */
202         retimeChapters();
203         if(b_fake_ordered)
204             b_ordered = true;
205     }
206
207 #if MKV_DEBUG
208     msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-BEGIN --" );
209     print();
210     msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-END --" );
211 #endif
212 }
213
214 virtual_edition_c::~virtual_edition_c()
215 {
216     for( size_t i = 0; i < chapters.size(); i++ )
217         delete chapters[i];
218 }
219
220 void virtual_edition_c::retimeSubChapters( virtual_chapter_c * p_vchap )
221 {
222     int64_t stop_time = p_vchap->i_virtual_stop_time;
223     for( size_t i = p_vchap->sub_chapters.size(); i-- > 0; )
224     {
225         virtual_chapter_c * p_vsubchap = p_vchap->sub_chapters[i];
226         p_vsubchap->i_virtual_start_time += p_vchap->i_virtual_start_time;
227
228         /*FIXME we artificially extend stop time if they were there before...*/
229         /* Just for comfort*/
230         p_vsubchap->i_virtual_stop_time = stop_time;
231         stop_time = p_vsubchap->i_virtual_start_time;
232
233         retimeSubChapters( p_vsubchap );
234     }
235 }
236
237 void virtual_edition_c::retimeChapters()
238 {
239     /* This function is just meant to be used on unordered chapters */
240     if( b_ordered )
241         return;
242
243     i_duration = 0;
244
245     /* On non ordered editions we have one top chapter == one segment */
246     for( size_t i = 0; i < chapters.size(); i++ )
247     {
248         virtual_chapter_c * p_vchap = chapters[i];
249
250         p_vchap->i_virtual_start_time = i_duration;
251         i_duration += p_vchap->p_segment->i_duration * 1000;
252         p_vchap->i_virtual_stop_time = i_duration;
253
254         retimeSubChapters( p_vchap );
255     }
256 }
257
258 virtual_segment_c::virtual_segment_c( std::vector<matroska_segment_c*> * p_opened_segments )
259 {
260     /* Main segment */
261     matroska_segment_c *p_segment = (*p_opened_segments)[0];
262     i_current_edition = 0;
263     i_sys_title = 0;
264     p_current_chapter = NULL;
265
266     for( size_t i = 0; i < p_segment->stored_editions.size(); i++ )
267     {
268         /* Get the default edition, if non use the first one */
269         if( p_segment->stored_editions[i]->b_default )
270             i_current_edition = i;
271
272         /* Create a virtual edition from opened */
273         virtual_edition_c * p_vedition = new virtual_edition_c( p_segment->stored_editions[i], p_opened_segments );
274
275         /*FIXME if p_vedition failed...*/
276
277         editions.push_back( p_vedition );
278     }
279     /*if we don't have edition create a dummy one*/
280     if( !p_segment->stored_editions.size() )
281     {
282         virtual_edition_c * p_vedition = new virtual_edition_c( NULL, p_opened_segments );
283         editions.push_back( p_vedition );
284     }
285
286     /* Set current chapter */
287     p_current_chapter = editions[i_current_edition]->getChapterbyTimecode(0);
288
289 }
290
291 virtual_segment_c::~virtual_segment_c()
292 {
293     for( size_t i = 0; i < editions.size(); i++ )
294         delete editions[i];
295 }
296
297 virtual_chapter_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
298                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
299                                     const void *p_cookie,
300                                     size_t i_cookie_size )
301 {
302     virtual_edition_c * p_ved = CurrentEdition();
303     if( p_ved )
304         return p_ved->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
305
306     return NULL;
307 }
308
309
310 virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( unsigned int codec_id,
311                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
312                                     const void *p_cookie,
313                                     size_t i_cookie_size )
314 {
315     if( !p_edition )
316         return NULL;
317
318     for( size_t i = 0; i < chapters.size(); i++ )
319     {
320         virtual_chapter_c * p_result = chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
321         if( p_result )
322             return p_result;
323     }
324     return NULL;
325 }
326
327
328
329 virtual_chapter_c * virtual_chapter_c::BrowseCodecPrivate( unsigned int codec_id,
330                                     bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
331                                     const void *p_cookie,
332                                     size_t i_cookie_size )
333 {
334     if( !p_chapter )
335         return NULL;
336
337     if( p_chapter->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size ) )
338         return this;
339
340     for( size_t i = 0; i < sub_chapters.size(); i++ )
341     {
342         virtual_chapter_c * p_result = sub_chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
343         if( p_result )
344             return p_result;
345     }
346     return NULL;
347 }
348
349 virtual_chapter_c* virtual_chapter_c::getSubChapterbyTimecode( int64_t time )
350 {
351     for( size_t i = 0; i < sub_chapters.size(); i++ )
352     {
353         if( time >= sub_chapters[i]->i_virtual_start_time && time < sub_chapters[i]->i_virtual_stop_time )
354             return sub_chapters[i]->getSubChapterbyTimecode( time );
355     }
356
357     return this;
358 }
359
360 virtual_chapter_c* virtual_edition_c::getChapterbyTimecode( int64_t time )
361 {
362     for( size_t i = 0; i < chapters.size(); i++ )
363     {
364         if( time >= chapters[i]->i_virtual_start_time &&
365             ( chapters[i]->i_virtual_stop_time < 0 || time < chapters[i]->i_virtual_stop_time ) )
366             /*with the current implementation only the last chapter can have a negative virtual_stop_time*/
367             return chapters[i]->getSubChapterbyTimecode( time );
368     }
369
370     return NULL;
371 }
372
373 bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
374 {
375     demux_sys_t & sys = *demux.p_sys;
376     virtual_chapter_c *p_cur_chapter;
377     virtual_edition_c * p_cur_edition = editions[ i_current_edition ];
378
379     bool b_has_seeked = false;
380
381     p_cur_chapter = p_cur_edition->getChapterbyTimecode( sys.i_pts );
382
383     /* we have moved to a new chapter */
384     if ( p_cur_chapter != NULL && p_current_chapter != p_cur_chapter )
385         {
386             msg_Dbg( &demux, "NEW CHAPTER %"PRId64, sys.i_pts );
387             if ( p_cur_edition->b_ordered )
388             {
389                 /* FIXME EnterAndLeave has probably been broken for a long time */
390                 // Leave/Enter up to the link point
391                 b_has_seeked = p_cur_chapter->EnterAndLeave( p_current_chapter );
392                 if ( !b_has_seeked )
393                 {
394                     // only physically seek if necessary
395                     if ( p_current_chapter == NULL ||
396                         ( p_current_chapter && p_current_chapter->p_segment != p_cur_chapter->p_segment ) ||
397                         ( p_current_chapter->p_chapter->i_end_time != p_cur_chapter->p_chapter->i_start_time ))
398                     {
399                         Seek( demux, p_cur_chapter->i_virtual_start_time, 0, p_cur_chapter, -1 );
400                         return true;
401                     }
402                 }
403                 sys.i_start_pts = p_cur_chapter->i_virtual_start_time;;
404             }
405
406             p_current_chapter = p_cur_chapter;
407             if ( p_cur_chapter->i_seekpoint_num > 0 )
408             {
409                 demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
410                 demux.info.i_title = sys.i_current_title = i_sys_title;
411                 demux.info.i_seekpoint = p_cur_chapter->i_seekpoint_num - 1;
412             }
413
414             return b_has_seeked;
415         }
416         else if ( p_cur_chapter == NULL )
417         {
418             /* out of the scope of the data described by chapters, leave the edition */
419             if ( p_cur_edition->b_ordered && p_current_chapter != NULL )
420             {
421                 /* TODO */
422                 if ( !p_cur_edition->p_edition->EnterAndLeave( p_current_chapter->p_chapter, false ) )
423                     p_current_chapter = NULL;
424                 else
425                     return true;
426             }
427         }
428     return false;
429 }
430
431 bool virtual_chapter_c::EnterAndLeave( virtual_chapter_c *p_item, bool b_enter )
432 {
433     if( !p_chapter )
434         return false;
435
436     return p_chapter->EnterAndLeave( p_item->p_chapter, b_enter );
437 }
438
439 void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, 
440                               virtual_chapter_c *p_chapter, int64_t i_global_position )
441 {
442     demux_sys_t *p_sys = demuxer.p_sys;
443
444
445     /* find the actual time for an ordered edition */
446     if ( p_chapter == NULL )
447         /* 1st, we need to know in which chapter we are */
448         p_chapter = editions[ i_current_edition ]->getChapterbyTimecode( i_date );
449
450     if ( p_chapter != NULL )
451     {
452         i_time_offset = p_chapter->i_virtual_start_time - ( ( p_chapter->p_chapter )? p_chapter->p_chapter->i_start_time : 0 );
453         p_sys->i_chapter_time = i_time_offset - p_chapter->p_segment->i_start_time;
454         if ( p_chapter->p_chapter && p_chapter->i_seekpoint_num > 0 )
455         {
456             demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
457             demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
458             demuxer.info.i_seekpoint = p_chapter->i_seekpoint_num - 1;
459         }
460
461         if( p_current_chapter->p_segment != p_chapter->p_segment )
462         {
463             p_chapter->p_segment->Select( i_date );
464             p_current_chapter->p_segment->UnSelect();
465         }
466         p_current_chapter = p_chapter;
467
468         p_chapter->p_segment->Seek( i_date, i_time_offset, i_global_position );
469     }
470 }
471
472 virtual_chapter_c * virtual_chapter_c::FindChapter( int64_t i_find_uid )
473 {
474     if( p_chapter && ( p_chapter->i_uid == i_find_uid ) )
475         return this;
476
477     for( size_t i = 0; i < sub_chapters.size(); i++ )
478     {
479         virtual_chapter_c * p_res = sub_chapters[i]->FindChapter( i_find_uid );
480         if( p_res )
481             return p_res;
482     }
483
484     return NULL;
485 }
486
487 virtual_chapter_c * virtual_segment_c::FindChapter( int64_t i_find_uid )
488 {
489     virtual_edition_c * p_edition = editions[i_current_edition];
490
491     for( size_t i = 0; p_edition->chapters.size(); i++ )
492     {
493         virtual_chapter_c * p_chapter = p_edition->chapters[i]->FindChapter( i_find_uid );
494         if( p_chapter )
495             return p_chapter;
496     }
497     return NULL;
498 }
499
500 int virtual_chapter_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
501 {
502     if ( p_chapter && ( !p_chapter->b_display_seekpoint || p_chapter->psz_name == "" ) )
503     {
504         p_chapter->psz_name = p_chapter->GetCodecName();
505         if ( p_chapter->psz_name != "" )
506             p_chapter->b_display_seekpoint = true;
507     }
508
509     if ( ( p_chapter && p_chapter->b_display_seekpoint &&
510          ( ( sub_chapters.size() > 0 && i_virtual_start_time != sub_chapters[0]->i_virtual_start_time) ||
511            sub_chapters.size() == 0 ) ) || !p_chapter )
512     {
513         seekpoint_t *sk = vlc_seekpoint_New();
514
515         sk->i_time_offset = i_virtual_start_time;
516         if( p_chapter )
517             sk->psz_name = strdup( p_chapter->psz_name.c_str() );
518         else
519             sk->psz_name = strdup("dummy chapter");
520
521         /* A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value. */
522         title.i_seekpoint++;
523         title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
524                                  title.i_seekpoint * sizeof( seekpoint_t* ) );
525         title.seekpoint[title.i_seekpoint-1] = sk;
526
527         if ( (p_chapter && p_chapter->b_user_display ) ||  !p_chapter )
528             i_user_chapters++;
529     }
530     i_seekpoint_num = i_user_chapters;
531
532     for( size_t i = 0; i < sub_chapters.size(); i++ )
533         sub_chapters[i]->PublishChapters( title, i_user_chapters, i_level + 1 );
534
535     return i_user_chapters;
536 }
537
538
539 int virtual_edition_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
540 {
541
542     /* HACK for now don't expose edition as a seekpoint if its start time is the same than it's first chapter */
543     if( chapters.size() > 0 &&
544         chapters[0]->i_virtual_start_time && p_edition )
545     {
546         seekpoint_t *sk = vlc_seekpoint_New();
547
548         sk->i_time_offset = 0;
549         sk->psz_name = strdup( p_edition->psz_name.c_str() );
550
551         title.i_seekpoint++;
552         title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
553                              title.i_seekpoint * sizeof( seekpoint_t* ) );
554         title.seekpoint[title.i_seekpoint - 1] = sk;
555         i_level++;
556
557         i_user_chapters++;
558         i_seekpoint_num = i_user_chapters;
559     }
560
561 //    if( chapters.size() > 1 )
562         for( size_t i = 0; i < chapters.size(); i++ )
563             chapters[i]->PublishChapters( title, i_user_chapters, i_level );
564
565     return i_user_chapters;
566 }
567
568 std::string virtual_edition_c::GetMainName()
569 {
570     if( p_edition )
571         return p_edition->GetMainName();
572
573     return std::string("");
574 }
575
576 bool virtual_chapter_c::Enter( bool b_do_subs )
577 {
578     if( p_chapter )
579         return p_chapter->Enter( b_do_subs );
580     return false;
581 }
582
583 bool virtual_chapter_c::Leave( bool b_do_subs )
584 {
585     if( p_chapter )
586         return p_chapter->Leave( b_do_subs );
587     return false;
588 }
589
590 #if MKV_DEBUG
591 void virtual_chapter_c::print() 
592 {
593     msg_Dbg( &p_segment->sys.demuxer, "*** chapter %"PRId64" - %"PRId64" (%u)",
594              i_virtual_start_time, i_virtual_stop_time, sub_chapters.size() );
595     for( size_t i = 0; i < sub_chapters.size(); i++ )
596         sub_chapters[i]->print();
597 }
598 #endif