2 /*****************************************************************************
3 * mkv.cpp : matroska demuxer
4 *****************************************************************************
5 * Copyright (C) 2003-2004 VLC authors and VideoLAN
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * Steve Lhomme <steve.lhomme@free.fr>
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.
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.
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 *****************************************************************************/
27 #include "stream_io_callback.hpp"
28 #include "Ebml_parser.hpp"
32 event_thread_t::event_thread_t(demux_t *p_demux) : p_demux(p_demux)
34 vlc_mutex_init( &lock );
35 vlc_cond_init( &wait );
38 event_thread_t::~event_thread_t()
41 vlc_cond_destroy( &wait );
42 vlc_mutex_destroy( &lock );
45 void event_thread_t::SetPci(const pci_t *data)
47 vlc_mutex_locker l(&lock);
51 #ifndef WORDS_BIGENDIAN
52 for( uint8_t button = 1; button <= pci_packet.hli.hl_gi.btn_ns; button++) {
53 btni_t *button_ptr = &(pci_packet.hli.btnit[button-1]);
54 binary *p_data = (binary*) button_ptr;
56 uint16 i_x_start = ((p_data[0] & 0x3F) << 4 ) + ( p_data[1] >> 4 );
57 uint16 i_x_end = ((p_data[1] & 0x03) << 8 ) + p_data[2];
58 uint16 i_y_start = ((p_data[3] & 0x3F) << 4 ) + ( p_data[4] >> 4 );
59 uint16 i_y_end = ((p_data[4] & 0x03) << 8 ) + p_data[5];
60 button_ptr->x_start = i_x_start;
61 button_ptr->x_end = i_x_end;
62 button_ptr->y_start = i_y_start;
63 button_ptr->y_end = i_y_end;
66 for ( uint8_t i = 0; i<3; i++ )
67 for ( uint8_t j = 0; j<2; j++ )
68 pci_packet.hli.btn_colit.btn_coli[i][j] = U32_AT( &pci_packet.hli.btn_colit.btn_coli[i][j] );
73 is_running = !vlc_clone( &thread, EventThread, this, VLC_THREAD_PRIORITY_LOW );
76 void event_thread_t::ResetPci()
81 vlc_mutex_lock( &lock );
83 vlc_cond_signal( &wait );
84 vlc_mutex_unlock( &lock );
86 vlc_join( thread, NULL );
89 int event_thread_t::EventMouse( vlc_object_t *p_this, char const *psz_var,
90 vlc_value_t oldval, vlc_value_t newval, void *p_data )
92 VLC_UNUSED( oldval ); VLC_UNUSED( newval );
93 event_thread_t *p_ev = (event_thread_t *) p_data;
94 vlc_mutex_lock( &p_ev->lock );
95 if( psz_var[6] == 'c' )
97 p_ev->b_clicked = true;
98 msg_Dbg( p_this, "Event Mouse: clicked");
100 else if( psz_var[6] == 'm' )
101 p_ev->b_moved = true;
102 vlc_cond_signal( &p_ev->wait );
103 vlc_mutex_unlock( &p_ev->lock );
108 int event_thread_t::EventKey( vlc_object_t *p_this, char const *,
109 vlc_value_t, vlc_value_t newval, void *p_data )
111 event_thread_t *p_ev = (event_thread_t *) p_data;
112 vlc_mutex_lock( &p_ev->lock );
113 p_ev->i_key_action = newval.i_int;
114 vlc_cond_signal( &p_ev->wait );
115 vlc_mutex_unlock( &p_ev->lock );
116 msg_Dbg( p_this, "Event Key");
121 int event_thread_t::EventInput( vlc_object_t *p_this, char const *,
122 vlc_value_t, vlc_value_t newval, void *p_data )
124 VLC_UNUSED( p_this );
125 event_thread_t *p_ev = (event_thread_t *) p_data;
126 vlc_mutex_lock( &p_ev->lock );
127 if( newval.i_int == INPUT_EVENT_VOUT )
129 p_ev->b_vout |= true;
130 vlc_cond_signal( &p_ev->wait );
132 vlc_mutex_unlock( &p_ev->lock );
137 void event_thread_t::EventThread()
139 demux_sys_t *p_sys = p_demux->p_sys;
140 vlc_object_t *p_vout = NULL;
141 int canc = vlc_savecancel ();
148 /* catch all key event */
149 var_AddCallback( p_demux->p_libvlc, "key-action", EventKey, this );
150 /* catch input event */
151 var_AddCallback( p_sys->p_input, "intf-event", EventInput, this );
156 vlc_mutex_lock( &lock );
157 while( !b_abort && !i_key_action && !b_moved && !b_clicked && !b_vout)
158 vlc_cond_wait( &wait, &lock );
162 vlc_mutex_unlock( &lock );
169 msg_Dbg( p_demux, "Handle Key Event");
171 pci_t *pci = &pci_packet;
173 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
175 switch( i_key_action )
177 case ACTIONID_NAV_LEFT:
178 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
180 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
181 if ( p_button_ptr->left > 0 && p_button_ptr->left <= pci->hli.hl_gi.btn_ns )
183 i_curr_button = p_button_ptr->left;
184 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
185 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
186 if ( button_ptr.auto_action_mode )
188 vlc_mutex_unlock( &lock );
189 vlc_mutex_lock( &p_sys->lock_demuxer );
191 // process the button action
192 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
194 vlc_mutex_unlock( &p_sys->lock_demuxer );
195 vlc_mutex_lock( &lock );
200 case ACTIONID_NAV_RIGHT:
201 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
203 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
204 if ( p_button_ptr->right > 0 && p_button_ptr->right <= pci->hli.hl_gi.btn_ns )
206 i_curr_button = p_button_ptr->right;
207 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
208 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
209 if ( button_ptr.auto_action_mode )
211 vlc_mutex_unlock( &lock );
212 vlc_mutex_lock( &p_sys->lock_demuxer );
214 // process the button action
215 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
217 vlc_mutex_unlock( &p_sys->lock_demuxer );
218 vlc_mutex_lock( &lock );
223 case ACTIONID_NAV_UP:
224 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
226 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
227 if ( p_button_ptr->up > 0 && p_button_ptr->up <= pci->hli.hl_gi.btn_ns )
229 i_curr_button = p_button_ptr->up;
230 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
231 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
232 if ( button_ptr.auto_action_mode )
234 vlc_mutex_unlock( &lock );
235 vlc_mutex_lock( &p_sys->lock_demuxer );
237 // process the button action
238 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
240 vlc_mutex_unlock( &p_sys->lock_demuxer );
241 vlc_mutex_lock( &lock );
246 case ACTIONID_NAV_DOWN:
247 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
249 btni_t *p_button_ptr = &(pci->hli.btnit[i_curr_button-1]);
250 if ( p_button_ptr->down > 0 && p_button_ptr->down <= pci->hli.hl_gi.btn_ns )
252 i_curr_button = p_button_ptr->down;
253 p_sys->dvd_interpretor.SetSPRM( 0x88, i_curr_button );
254 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
255 if ( button_ptr.auto_action_mode )
257 vlc_mutex_unlock( &lock );
258 vlc_mutex_lock( &p_sys->lock_demuxer );
260 // process the button action
261 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
263 vlc_mutex_unlock( &p_sys->lock_demuxer );
264 vlc_mutex_lock( &lock );
269 case ACTIONID_NAV_ACTIVATE:
270 if ( i_curr_button > 0 && i_curr_button <= pci->hli.hl_gi.btn_ns )
272 btni_t button_ptr = pci->hli.btnit[i_curr_button-1];
274 vlc_mutex_unlock( &lock );
275 vlc_mutex_lock( &p_sys->lock_demuxer );
277 // process the button action
278 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
280 vlc_mutex_unlock( &p_sys->lock_demuxer );
281 vlc_mutex_lock( &lock );
291 if( p_vout && ( b_moved || b_clicked ) )
295 var_GetCoords( p_vout, "mouse-moved", &x, &y );
296 pci_t *pci = &pci_packet;
304 msg_Dbg( p_demux, "Handle Mouse Event: Mouse clicked x(%d)*y(%d)", x, y);
306 // get current button
308 dist = 0x08000000; /* >> than (720*720)+(567*567); */
309 for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++)
311 btni_t *button_ptr = &(pci->hli.btnit[button-1]);
313 if(((unsigned)x >= button_ptr->x_start)
314 && ((unsigned)x <= button_ptr->x_end)
315 && ((unsigned)y >= button_ptr->y_start)
316 && ((unsigned)y <= button_ptr->y_end))
318 mx = (button_ptr->x_start + button_ptr->x_end)/2;
319 my = (button_ptr->y_start + button_ptr->y_end)/2;
322 d = (dx*dx) + (dy*dy);
323 /* If the mouse is within the button and the mouse is closer
324 * to the center of this button then it is the best choice. */
334 btni_t button_ptr = pci->hli.btnit[best-1];
335 uint16 i_curr_button = p_sys->dvd_interpretor.GetSPRM( 0x88 );
337 msg_Dbg( &p_sys->demuxer, "Clicked button %d", best );
338 vlc_mutex_unlock( &lock );
339 vlc_mutex_lock( &p_sys->lock_demuxer );
341 // process the button action
342 p_sys->dvd_interpretor.SetSPRM( 0x88, best );
343 p_sys->dvd_interpretor.Interpret( button_ptr.cmd.bytes, 8 );
345 msg_Dbg( &p_sys->demuxer, "Processed button %d", best );
348 if ( best != i_curr_button )
352 if(button_ptr.btn_coln != 0) {
353 i_palette = pci->hli.btn_colit.btn_coli[button_ptr.btn_coln-1][1];
358 for( int i = 0; i < 4; i++ )
360 uint32_t i_yuv = 0xFF;//p_sys->clut[(hl.palette>>(16+i*4))&0x0f];
361 uint8_t i_alpha = (i_palette>>(i*4))&0x0f;
362 i_alpha = i_alpha == 0xf ? 0xff : i_alpha << 4;
364 p_sys->palette[i][0] = (i_yuv >> 16) & 0xff;
365 p_sys->palette[i][1] = (i_yuv >> 0) & 0xff;
366 p_sys->palette[i][2] = (i_yuv >> 8) & 0xff;
367 p_sys->palette[i][3] = i_alpha;
370 vlc_global_lock( VLC_HIGHLIGHT_MUTEX );
371 var_SetInteger( p_sys->p_input, "x-start",
372 button_ptr.x_start );
373 var_SetInteger( p_sys->p_input, "x-end",
375 var_SetInteger( p_sys->p_input, "y-start",
376 button_ptr.y_start );
377 var_SetInteger( p_sys->p_input, "y-end",
379 var_SetAddress( p_sys->p_input, "menu-palette",
381 var_SetBool( p_sys->p_input, "highlight", true );
382 vlc_global_unlock( VLC_HIGHLIGHT_MUTEX );
384 vlc_mutex_unlock( &p_sys->lock_demuxer );
385 vlc_mutex_lock( &lock );
390 // dvdnav_mouse_select( NULL, pci, x, y );
398 vlc_mutex_unlock( &lock );
400 /* Always check vout */
403 p_vout = (vlc_object_t*) input_GetVout(p_sys->p_input);
406 var_AddCallback( p_vout, "mouse-moved", EventMouse, this );
407 var_AddCallback( p_vout, "mouse-clicked", EventMouse, this );
412 /* Release callback */
415 var_DelCallback( p_vout, "mouse-moved", EventMouse, this );
416 var_DelCallback( p_vout, "mouse-clicked", EventMouse, this );
417 vlc_object_release( p_vout );
419 var_DelCallback( p_sys->p_input, "intf-event", EventInput, this );
420 var_DelCallback( p_demux->p_libvlc, "key-action", EventKey, this );
422 vlc_restorecancel (canc);
425 void *event_thread_t::EventThread(void *data)
427 static_cast<event_thread_t*>(data)->EventThread();
432 demux_sys_t::~demux_sys_t()
436 for ( i=0; i<streams.size(); i++ )
438 for ( i=0; i<opened_segments.size(); i++ )
439 delete opened_segments[i];
440 for ( i=0; i<used_segments.size(); i++ )
441 delete used_segments[i];
442 for ( i=0; i<stored_attachments.size(); i++ )
443 delete stored_attachments[i];
444 if( meta ) vlc_meta_Delete( meta );
446 while( titles.size() )
447 { vlc_input_title_Delete( titles.back() ); titles.pop_back();}
449 vlc_mutex_destroy( &lock_demuxer );
453 matroska_stream_c *demux_sys_t::AnalyseAllSegmentsFound( demux_t *p_demux, EbmlStream *p_estream, bool b_initial )
456 EbmlElement *p_l0, *p_l1, *p_l2;
457 bool b_keep_stream = false, b_keep_segment = false;
459 /* verify the EBML Header... it shouldn't be bigger than 1kB */
460 p_l0 = p_estream->FindNextID(EBML_INFO(EbmlHead), 1024);
463 msg_Err( p_demux, "No EBML header found" );
467 /* verify we can read this Segment */
470 p_l0->Read(*p_estream, EBML_CLASS_CONTEXT(EbmlHead), i_upper_lvl, p_l0, true);
474 msg_Err(p_demux, "EBML Header Read failed");
478 EDocType doc_type = GetChild<EDocType>(*static_cast<EbmlHead*>(p_l0));
479 if (std::string(doc_type) != "matroska" && std::string(doc_type) != "webm" )
481 msg_Err( p_demux, "Not a Matroska file : DocType = %s ", std::string(doc_type).c_str());
485 EDocTypeReadVersion doc_read_version = GetChild<EDocTypeReadVersion>(*static_cast<EbmlHead*>(p_l0));
486 if (uint64(doc_read_version) > 2)
488 msg_Err( p_demux, "matroska file needs version %" PRId64 " but only versions 1 & 2 supported", uint64(doc_read_version));
495 // find all segments in this file
496 p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
502 matroska_stream_c *p_stream1 = new matroska_stream_c();
506 if ( MKV_IS_ID( p_l0, KaxSegment) )
509 matroska_segment_c *p_segment1 = new matroska_segment_c( *this, *p_estream );
511 ep = new EbmlParser(p_estream, p_l0, &demuxer,
512 var_InheritBool( &demuxer, "mkv-use-dummy" ) );
514 p_segment1->segment = (KaxSegment*)p_l0;
516 while ((p_l1 = ep->Get()))
518 if (MKV_IS_ID(p_l1, KaxInfo))
520 // find the families of this segment
521 KaxInfo *p_info = static_cast<KaxInfo*>(p_l1);
522 b_keep_segment = b_initial;
523 if( unlikely( p_info->IsFiniteSize() && p_info->GetSize() >= SIZE_MAX ) )
525 msg_Err( p_demux, "KaxInfo too big aborting" );
530 p_info->Read(*p_estream, EBML_CLASS_CONTEXT(KaxInfo), i_upper_lvl, p_l2, true);
534 msg_Err( p_demux, "KaxInfo found but corrupted");
537 for( size_t i = 0; i < p_info->ListSize(); i++ )
539 EbmlElement *l = (*p_info)[i];
541 if( MKV_IS_ID( l, KaxSegmentUID ) )
543 KaxSegmentUID *p_uid = static_cast<KaxSegmentUID*>(l);
544 b_keep_segment = (FindSegment( *p_uid ) == NULL);
545 delete p_segment1->p_segment_uid;
546 p_segment1->p_segment_uid = new KaxSegmentUID(*p_uid);
547 if ( !b_keep_segment )
548 break; // this segment is already known
550 else if( MKV_IS_ID( l, KaxPrevUID ) )
552 p_segment1->p_prev_segment_uid = new KaxPrevUID( *static_cast<KaxPrevUID*>(l) );
553 p_segment1->b_ref_external_segments = true;
555 else if( MKV_IS_ID( l, KaxNextUID ) )
557 p_segment1->p_next_segment_uid = new KaxNextUID( *static_cast<KaxNextUID*>(l) );
558 p_segment1->b_ref_external_segments = true;
560 else if( MKV_IS_ID( l, KaxSegmentFamily ) )
562 KaxSegmentFamily *p_fam = new KaxSegmentFamily( *static_cast<KaxSegmentFamily*>(l) );
563 p_segment1->families.push_back( p_fam );
566 if( b_keep_segment || !p_segment1->p_segment_uid )
567 opened_segments.push_back( p_segment1 );
571 if ( b_keep_segment || !p_segment1->p_segment_uid )
573 b_keep_stream = true;
574 p_stream1->segments.push_back( p_segment1 );
578 p_segment1->segment = NULL;
582 if (p_l0->IsFiniteSize() )
584 p_l0->SkipData(*p_estream, KaxMatroska_Context);
585 p_l0 = p_estream->FindNextID(EBML_INFO(KaxSegment), UINT64_MAX);
593 if ( !b_keep_stream )
602 void demux_sys_t::InitUi()
604 msg_Dbg( &demuxer, "Starting the UI Hook" );
606 /* FIXME hack hack hack hack FIXME */
607 /* Get p_input and create variable */
608 p_input = demux_GetParentInput( &demuxer );
611 var_Create( p_input, "x-start", VLC_VAR_INTEGER );
612 var_Create( p_input, "y-start", VLC_VAR_INTEGER );
613 var_Create( p_input, "x-end", VLC_VAR_INTEGER );
614 var_Create( p_input, "y-end", VLC_VAR_INTEGER );
615 var_Create( p_input, "color", VLC_VAR_ADDRESS );
616 var_Create( p_input, "menu-palette", VLC_VAR_ADDRESS );
617 var_Create( p_input, "highlight", VLC_VAR_BOOL );
620 /* Now create our event thread catcher */
621 p_ev = new event_thread_t(&demuxer);
624 void demux_sys_t::CleanUi()
631 var_Destroy( p_input, "highlight" );
632 var_Destroy( p_input, "x-start" );
633 var_Destroy( p_input, "x-end" );
634 var_Destroy( p_input, "y-start" );
635 var_Destroy( p_input, "y-end" );
636 var_Destroy( p_input, "color" );
637 var_Destroy( p_input, "menu-palette" );
639 vlc_object_release( p_input );
642 msg_Dbg( &demuxer, "Stopping the UI Hook" );
645 void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
647 for (size_t i=0; i<opened_segments.size(); i++)
649 opened_segments[i]->PreloadFamily( of_segment );
653 // preload all the linked segments for all preloaded segments
654 bool demux_sys_t::PreloadLinked()
657 virtual_segment_c *p_seg;
659 p_current_segment = VirtualFromSegments( &opened_segments );
660 if ( !p_current_segment )
663 used_segments.push_back( p_current_segment );
665 // publish all editions of all usable segment
666 for ( i=0; i< used_segments.size(); i++ )
668 p_seg = used_segments[i];
669 if ( p_seg->Editions() != NULL )
671 for ( j=0; j<p_seg->Editions()->size(); j++ )
673 virtual_edition_c * p_ved = (*p_seg->Editions())[j];
674 input_title_t *p_title = vlc_input_title_New();
677 // TODO use a name for each edition, let the TITLE deal with a codec name
678 if ( p_title->psz_name == NULL )
680 if( p_ved->GetMainName().length() )
681 p_title->psz_name = strdup( p_ved->GetMainName().c_str() );
684 /* Check in tags if the edition has a name */
686 /* We use only the tags of the first segment as it contains the edition */
687 std::vector<Tag*> &tags = opened_segments[0]->tags;
688 uint64_t i_ed_uid = 0;
689 if( p_ved->p_edition )
690 i_ed_uid = (uint64_t) p_ved->p_edition->i_uid;
692 for( size_t k = 0; k < tags.size(); k++ )
694 if( tags[k]->i_tag_type == EDITION_UID && tags[k]->i_uid == i_ed_uid )
695 for( size_t l = 0; l < tags[k]->simple_tags.size(); l++ )
697 SimpleTag * p_st = tags[k]->simple_tags[l];
698 if( !strcmp(p_st->psz_tag_name,"TITLE") )
700 msg_Dbg( &demuxer, "Using title \"%s\" from tag for edition %" PRIu64, p_st->p_value, i_ed_uid );
701 p_title->psz_name = strdup( p_st->p_value );
707 if( !p_title->psz_name &&
708 asprintf(&(p_title->psz_name), "%s %d", N_("Segment"), (int)ij) == -1 )
709 p_title->psz_name = NULL;
715 p_ved->PublishChapters( *p_title, i_chapters, 0 );
717 // Input duration into i_length
718 p_title->i_length = p_ved->i_duration;
720 titles.push_back( p_title );
723 p_seg->i_sys_title = p_seg->i_current_edition;
726 // TODO decide which segment should be first used (VMG for DVD)
731 void demux_sys_t::FreeUnused()
734 for( i = 0; i < streams.size(); i++ )
737 struct matroska_stream_c *p_s = streams[i];
738 for( size_t j = 0; j < p_s->segments.size(); j++ )
740 if( p_s->segments[j]->b_preloaded )
752 for( i = 0; i < opened_segments.size(); i++)
754 if( !opened_segments[i]->b_preloaded )
756 delete opened_segments[i];
757 opened_segments[i] = NULL;
762 virtual_segment_c *demux_sys_t::VirtualFromSegments( std::vector<matroska_segment_c*> *p_segments ) const
764 if ( p_segments->empty() )
766 virtual_segment_c *p_result = new virtual_segment_c( p_segments );
770 bool demux_sys_t::PreparePlayback( virtual_segment_c *p_new_segment )
772 if ( p_new_segment != NULL && p_new_segment != p_current_segment )
774 if ( p_current_segment != NULL && p_current_segment->CurrentSegment() != NULL )
775 p_current_segment->CurrentSegment()->UnSelect();
777 p_current_segment = p_new_segment;
778 i_current_title = p_new_segment->i_sys_title;
780 if( !p_current_segment->CurrentSegment() )
782 if( !p_current_segment->CurrentSegment()->b_cues )
783 msg_Warn( &p_current_segment->CurrentSegment()->sys.demuxer, "no cues/empty cues found->seek won't be precise" );
785 f_duration = p_current_segment->Duration();
787 /* add information */
788 p_current_segment->CurrentSegment()->InformationCreate( );
789 p_current_segment->CurrentSegment()->Select( 0 );
791 /* Seek to the beginning */
792 p_current_segment->Seek(p_current_segment->CurrentSegment()->sys.demuxer,
798 void demux_sys_t::JumpTo( virtual_segment_c & vsegment, virtual_chapter_c * p_chapter )
800 // if the segment is not part of the current segment, select the new one
801 if ( &vsegment != p_current_segment )
803 PreparePlayback( &vsegment );
808 if ( !p_chapter->p_chapter || !p_chapter->p_chapter->Enter( true ) )
810 // jump to the location in the found segment
811 vsegment.Seek( demuxer, p_chapter->i_virtual_start_time, -1, p_chapter, -1 );
817 matroska_segment_c *demux_sys_t::FindSegment( const EbmlBinary & uid ) const
819 for (size_t i=0; i<opened_segments.size(); i++)
821 if ( opened_segments[i]->p_segment_uid && *opened_segments[i]->p_segment_uid == uid )
822 return opened_segments[i];
827 virtual_chapter_c *demux_sys_t::BrowseCodecPrivate( unsigned int codec_id,
828 bool (*match)(const chapter_codec_cmds_c &data, const void *p_cookie, size_t i_cookie_size ),
829 const void *p_cookie,
830 size_t i_cookie_size,
831 virtual_segment_c * &p_segment_found )
833 virtual_chapter_c *p_result = NULL;
834 for (size_t i=0; i<used_segments.size(); i++)
836 p_result = used_segments[i]->BrowseCodecPrivate( codec_id, match, p_cookie, i_cookie_size );
837 if ( p_result != NULL )
839 p_segment_found = used_segments[i];
846 virtual_chapter_c *demux_sys_t::FindChapter( int64_t i_find_uid, virtual_segment_c * & p_segment_found )
848 virtual_chapter_c *p_result = NULL;
849 for (size_t i=0; i<used_segments.size(); i++)
851 p_result = used_segments[i]->FindChapter( i_find_uid );
852 if ( p_result != NULL )
854 p_segment_found = used_segments[i];