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 *****************************************************************************/
29 matroska_segment_c * getSegmentbyUID( KaxSegmentUID * p_uid, std::vector<matroska_segment_c*> *segments )
31 for( size_t i = 0; i < (*segments).size(); i++ )
33 if( *p_uid == *((*segments)[i]->p_segment_uid) )
34 return (*segments)[i];
39 virtual_chapter_c * virtual_chapter_c::CreateVirtualChapter( chapter_item_c * p_chap,
40 matroska_segment_c * p_main_segment,
41 std::vector<matroska_segment_c*> * segments,
42 int64_t * usertime_offset, bool b_ordered)
44 matroska_segment_c * p_segment = p_main_segment;
48 /* Dummy chapter use the whole segment */
49 return new virtual_chapter_c( p_segment, NULL, 0, p_segment->i_duration*1000 );
52 int64_t start = ( b_ordered )? *usertime_offset : p_chap->i_start_time;
53 int64_t stop = ( b_ordered )? ( *usertime_offset + p_chap->i_end_time - p_chap->i_start_time ) : p_chap->i_end_time;
55 if( p_chap->p_segment_uid &&
56 ( !( p_segment = getSegmentbyUID( (KaxSegmentUID*) p_chap->p_segment_uid,segments ) ) || !b_ordered ) )
58 msg_Warn( &p_main_segment->sys.demuxer,
59 "Couldn't find segment 0x%x or not ordered... - ignoring chapter %s",
60 *( (uint32_t *) p_chap->p_segment_uid->GetBuffer() ),p_chap->psz_name.c_str() );
65 if ( !p_segment->b_preloaded )
68 virtual_chapter_c * p_vchap = new virtual_chapter_c( p_segment, p_chap, start, stop );
73 int64_t tmp = *usertime_offset;
75 for( size_t i = 0; i < p_chap->sub_chapters.size(); i++ )
77 virtual_chapter_c * p_vsubchap = CreateVirtualChapter( p_chap->sub_chapters[i], p_segment, segments, &tmp, b_ordered );
80 p_vchap->sub_chapters.push_back( p_vsubchap );
83 if( tmp == *usertime_offset )
84 *usertime_offset += p_chap->i_end_time - p_chap->i_start_time;
86 *usertime_offset = tmp;
88 msg_Dbg( &p_main_segment->sys.demuxer,
89 "Virtual chapter %s from %"PRId64" to %"PRId64" - segment 0x%x",
90 p_chap->psz_name.c_str(), p_vchap->i_virtual_start_time, p_vchap->i_virtual_stop_time,
91 *(uint32_t*)p_vchap->p_segment->p_segment_uid->GetBuffer() );
96 virtual_chapter_c::~virtual_chapter_c()
98 for( size_t i = 0 ; i < sub_chapters.size(); i++ )
99 delete sub_chapters[i];
103 virtual_edition_c::virtual_edition_c( chapter_edition_c * p_edit, std::vector<matroska_segment_c*> *opened_segments)
105 matroska_segment_c *p_main_segment = (*opened_segments)[0];
108 int64_t usertime_offset = 0;
110 /* ordered chapters */
111 if( p_edition && p_edition->b_ordered )
114 for( size_t i = 0; i < p_edition->sub_chapters.size(); i++ )
116 virtual_chapter_c * p_vchap = virtual_chapter_c::CreateVirtualChapter( p_edition->sub_chapters[i],
117 p_main_segment, opened_segments,
118 &usertime_offset, b_ordered );
120 chapters.push_back( p_vchap );
122 i_duration = chapters[ chapters.size() - 1 ]->i_virtual_stop_time;
124 else /* Not ordered or no edition at all */
127 matroska_segment_c * p_cur = p_main_segment;
128 virtual_chapter_c * p_vchap = NULL;
131 /* check for prev linked segments */
132 /* FIXME to avoid infinite recursion we limit to 5 prev sould be better as parameter */
133 for( int limit = 0; limit < 5 && p_cur->p_prev_segment_uid ; limit++ )
135 matroska_segment_c * p_prev = NULL;
136 if( ( p_prev = getSegmentbyUID( p_cur->p_prev_segment_uid, opened_segments ) ) )
139 msg_Dbg( &p_main_segment->sys.demuxer, "Prev segment 0x%x found\n",
140 *(int32_t*)p_cur->p_prev_segment_uid->GetBuffer() );
142 /* Create virtual_chapter from the first edition if any */
143 chapter_item_c * p_chap = ( p_prev->stored_editions.size() > 0 )? ((chapter_item_c *)p_prev->stored_editions[0]) : NULL;
145 p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_prev, opened_segments, &tmp, b_ordered );
148 chapters.insert( chapters.begin(), p_vchap );
152 else /* segment not found */
158 /* Append the main segment */
159 p_vchap = virtual_chapter_c::CreateVirtualChapter( (chapter_item_c*) p_edit, p_main_segment,
160 opened_segments, &tmp, b_ordered );
162 chapters.push_back( p_vchap );
164 /* Append next linked segments */
165 for( int limit = 0; limit < 5 && p_cur->p_next_segment_uid; limit++ )
167 matroska_segment_c * p_next = NULL;
168 if( ( p_next = getSegmentbyUID( p_cur->p_next_segment_uid, opened_segments ) ) )
171 msg_Dbg( &p_main_segment->sys.demuxer, "Next segment 0x%x found\n",
172 *(int32_t*) p_cur->p_next_segment_uid->GetBuffer() );
174 /* Create virtual_chapter from the first edition if any */
175 chapter_item_c * p_chap = ( p_next->stored_editions.size() > 0 )?( (chapter_item_c *)p_next->stored_editions[0] ) : NULL;
177 p_vchap = virtual_chapter_c::CreateVirtualChapter( p_chap, p_next, opened_segments, &tmp, b_ordered );
180 chapters.push_back( p_vchap );
185 else /* segment not found */
189 /* Retime chapters */
194 msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-BEGIN --" );
196 msg_Dbg( &p_main_segment->sys.demuxer, "-- RECAP-END --" );
200 virtual_edition_c::~virtual_edition_c()
202 for( size_t i = 0; i < chapters.size(); i++ )
206 void virtual_edition_c::retimeSubChapters( virtual_chapter_c * p_vchap )
208 int64_t stop_time = p_vchap->i_virtual_stop_time;
209 for( size_t i = p_vchap->sub_chapters.size(); i-- > 0; )
211 virtual_chapter_c * p_vsubchap = p_vchap->sub_chapters[i];
212 p_vsubchap->i_virtual_start_time += p_vchap->i_virtual_start_time;
214 /*FIXME we artificially extend stop time if they were there before...*/
215 /* Just for comfort*/
216 p_vsubchap->i_virtual_stop_time = stop_time;
217 stop_time = p_vsubchap->i_virtual_start_time;
219 retimeSubChapters( p_vsubchap );
223 void virtual_edition_c::retimeChapters()
225 /* This function is just meant to be used on unordered chapters */
231 /* Sort by start time */
232 if( chapters.size() > 1 )
233 std::sort( chapters.begin(), chapters.end(), virtual_chapter_c::CompareTimecode );
235 /* On non ordered editions we have one top chapter == one segment */
236 for( size_t i = 0; i < chapters.size(); i++ )
238 virtual_chapter_c * p_vchap = chapters[i];
240 p_vchap->i_virtual_start_time = i_duration;
241 i_duration += p_vchap->p_segment->i_duration * 1000;
242 p_vchap->i_virtual_stop_time = i_duration;
244 retimeSubChapters( p_vchap );
248 virtual_segment_c::virtual_segment_c( std::vector<matroska_segment_c*> * p_opened_segments )
251 matroska_segment_c *p_segment = (*p_opened_segments)[0];
252 i_current_edition = 0;
254 p_current_chapter = NULL;
256 for( size_t i = 0; i < p_segment->stored_editions.size(); i++ )
258 /* Get the default edition, if non use the first one */
259 if( p_segment->stored_editions[i]->b_default )
260 i_current_edition = i;
262 /* Create a virtual edition from opened */
263 virtual_edition_c * p_vedition = new virtual_edition_c( p_segment->stored_editions[i], p_opened_segments );
265 /*FIXME if p_vedition failed...*/
267 editions.push_back( p_vedition );
269 /*if we don't have edition create a dummy one*/
270 if( !p_segment->stored_editions.size() )
272 virtual_edition_c * p_vedition = new virtual_edition_c( NULL, p_opened_segments );
273 editions.push_back( p_vedition );
276 /* Set current chapter */
277 p_current_chapter = editions[i_current_edition]->getChapterbyTimecode(0);
281 virtual_segment_c::~virtual_segment_c()
283 for( size_t i = 0; i < editions.size(); i++ )
287 virtual_chapter_c *virtual_segment_c::BrowseCodecPrivate( unsigned int codec_id,
288 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
289 const void *p_cookie,
290 size_t i_cookie_size )
292 virtual_edition_c * p_ved = CurrentEdition();
294 return p_ved->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
300 virtual_chapter_c * virtual_edition_c::BrowseCodecPrivate( unsigned int codec_id,
301 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
302 const void *p_cookie,
303 size_t i_cookie_size )
308 for( size_t i = 0; i < chapters.size(); i++ )
310 virtual_chapter_c * p_result = chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
319 virtual_chapter_c * virtual_chapter_c::BrowseCodecPrivate( unsigned int codec_id,
320 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
321 const void *p_cookie,
322 size_t i_cookie_size )
327 if( p_chapter->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size ) )
330 for( size_t i = 0; i < sub_chapters.size(); i++ )
332 virtual_chapter_c * p_result = sub_chapters[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
339 virtual_chapter_c* virtual_chapter_c::getSubChapterbyTimecode( int64_t time )
341 for( size_t i = 0; i < sub_chapters.size(); i++ )
343 if( time >= sub_chapters[i]->i_virtual_start_time && time < sub_chapters[i]->i_virtual_stop_time )
344 return sub_chapters[i]->getSubChapterbyTimecode( time );
350 virtual_chapter_c* virtual_edition_c::getChapterbyTimecode( int64_t time )
352 for( size_t i = 0; i < chapters.size(); i++ )
354 if( time >= chapters[i]->i_virtual_start_time && time < chapters[i]->i_virtual_stop_time )
355 return chapters[i]->getSubChapterbyTimecode( time );
361 bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
363 demux_sys_t & sys = *demux.p_sys;
364 virtual_chapter_c *p_cur_chapter;
365 virtual_edition_c * p_cur_edition = editions[ i_current_edition ];
367 bool b_has_seeked = false;
369 p_cur_chapter = p_cur_edition->getChapterbyTimecode( sys.i_pts );
371 /* we have moved to a new chapter */
372 if ( p_cur_chapter != NULL && p_current_chapter != p_cur_chapter )
374 msg_Dbg( &demux, "NEW CHAPTER %"PRId64, sys.i_pts );
375 if ( p_cur_edition->b_ordered )
377 /* FIXME EnterAndLeave has probably been broken for a long time */
378 // Leave/Enter up to the link point
379 b_has_seeked = p_cur_chapter->EnterAndLeave( p_current_chapter );
382 // only physically seek if necessary
383 if ( p_current_chapter == NULL ||
384 ( p_current_chapter->p_chapter->i_end_time != p_cur_chapter->p_chapter->i_start_time ) ||
385 ( p_current_chapter && p_current_chapter->p_segment != p_cur_chapter->p_segment ) )
387 /* hack : we have to use input to seek in order to clean buffers */
388 var_SetTime( demux.p_sys->p_input, "time", p_cur_chapter->i_virtual_start_time );
394 p_current_chapter = p_cur_chapter;
395 if ( p_cur_chapter->i_seekpoint_num > 0 )
397 demux.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
398 demux.info.i_title = sys.i_current_title = i_sys_title;
399 demux.info.i_seekpoint = p_cur_chapter->i_seekpoint_num - 1;
404 else if ( p_cur_chapter == NULL )
406 /* out of the scope of the data described by chapters, leave the edition */
407 if ( p_cur_edition->b_ordered && p_current_chapter != NULL )
410 if ( !p_cur_edition->p_edition->EnterAndLeave( p_current_chapter->p_chapter, false ) )
411 p_current_chapter = NULL;
419 bool virtual_chapter_c::EnterAndLeave( virtual_chapter_c *p_item, bool b_enter )
424 return p_chapter->EnterAndLeave( p_item->p_chapter, b_enter );
427 void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset,
428 virtual_chapter_c *p_chapter, int64_t i_global_position )
430 demux_sys_t *p_sys = demuxer.p_sys;
433 /* find the actual time for an ordered edition */
434 if ( p_chapter == NULL )
435 /* 1st, we need to know in which chapter we are */
436 p_chapter = editions[ i_current_edition ]->getChapterbyTimecode( i_date );
438 if ( p_chapter != NULL )
440 p_sys->i_chapter_time =
441 i_time_offset = p_chapter->i_virtual_start_time - ( ( p_chapter->p_chapter )? p_chapter->p_chapter->i_start_time : 0 );
442 if ( p_chapter->p_chapter && p_chapter->i_seekpoint_num > 0 )
444 demuxer.info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT;
445 demuxer.info.i_title = p_sys->i_current_title = i_sys_title;
446 demuxer.info.i_seekpoint = p_chapter->i_seekpoint_num - 1;
449 if( p_current_chapter->p_segment != p_chapter->p_segment )
451 p_current_chapter->p_segment->UnSelect();
452 es_out_Control( demuxer.out, ES_OUT_RESET_PCR );
453 p_chapter->p_segment->Select( i_date );
455 p_current_chapter = p_chapter;
457 p_chapter->p_segment->Seek( i_date, i_time_offset, i_global_position );
461 virtual_chapter_c * virtual_chapter_c::FindChapter( int64_t i_find_uid )
463 if( p_chapter && ( p_chapter->i_uid == i_find_uid ) )
466 for( size_t i = 0; i < sub_chapters.size(); i++ )
468 virtual_chapter_c * p_res = sub_chapters[i]->FindChapter( i_find_uid );
476 virtual_chapter_c * virtual_segment_c::FindChapter( int64_t i_find_uid )
478 virtual_edition_c * p_edition = editions[i_current_edition];
480 for( size_t i = 0; p_edition->chapters.size(); i++ )
482 virtual_chapter_c * p_chapter = p_edition->chapters[i]->FindChapter( i_find_uid );
489 int virtual_chapter_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
491 if ( p_chapter && ( !p_chapter->b_display_seekpoint || p_chapter->psz_name == "" ) )
493 p_chapter->psz_name = p_chapter->GetCodecName();
494 if ( p_chapter->psz_name != "" )
495 p_chapter->b_display_seekpoint = true;
498 if ( ( p_chapter && p_chapter->b_display_seekpoint &&
499 ( ( sub_chapters.size() > 0 && i_virtual_start_time != sub_chapters[0]->i_virtual_start_time) ||
500 sub_chapters.size() == 0 ) ) || !p_chapter )
502 seekpoint_t *sk = vlc_seekpoint_New();
504 sk->i_level = i_level;
505 sk->i_time_offset = i_virtual_start_time;
507 sk->psz_name = strdup( p_chapter->psz_name.c_str() );
509 sk->psz_name = strdup("dummy chapter");
511 /* A start time of '0' is ok. A missing ChapterTime element is ok, too, because '0' is its default value. */
513 title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
514 title.i_seekpoint * sizeof( seekpoint_t* ) );
515 title.seekpoint[title.i_seekpoint-1] = sk;
517 if ( (p_chapter && p_chapter->b_user_display ) || !p_chapter )
520 i_seekpoint_num = i_user_chapters;
522 for( size_t i = 0; i < sub_chapters.size(); i++ )
523 sub_chapters[i]->PublishChapters( title, i_user_chapters, i_level + 1 );
525 return i_user_chapters;
529 int virtual_edition_c::PublishChapters( input_title_t & title, int & i_user_chapters, int i_level )
532 /* HACK for now don't expose edition as a seekpoint if its start time is the same than it's first chapter */
533 if( chapters.size() > 0 && chapters[0]->i_virtual_start_time )
535 seekpoint_t *sk = vlc_seekpoint_New();
537 sk->i_level = i_level;
538 sk->i_time_offset = 0;
540 sk->psz_name = strdup( p_edition->psz_name.c_str() );
542 sk->psz_name = strdup( "Dummy edition" );
545 title.seekpoint = (seekpoint_t**)xrealloc( title.seekpoint,
546 title.i_seekpoint * sizeof( seekpoint_t* ) );
547 title.seekpoint[title.i_seekpoint - 1] = sk;
551 i_seekpoint_num = i_user_chapters;
554 for( size_t i = 0; i < chapters.size(); i++ )
555 chapters[i]->PublishChapters( title, i_user_chapters, i_level );
557 return i_user_chapters;
560 std::string virtual_edition_c::GetMainName()
563 return p_edition->GetMainName();
565 return std::string("");
568 bool virtual_chapter_c::Enter( bool b_do_subs )
571 return p_chapter->Enter( b_do_subs );
575 bool virtual_chapter_c::Leave( bool b_do_subs )
578 return p_chapter->Leave( b_do_subs );
583 void virtual_chapter_c::print()
585 msg_Dbg( &p_segment->sys.demuxer, "*** chapter %"PRId64" - %"PRId64" (%u)",
586 i_virtual_start_time, i_virtual_stop_time, sub_chapters.size() );
587 for( size_t i = 0; i < sub_chapters.size(); i++ )
588 sub_chapters[i]->print();